杰克逊JSON作为Java中的价值

时间:2017-10-27 22:36:06

标签: java spring serialization jackson

我在Spring MVC应用程序中使用Jackson。我想使用String值作为Java POJO的关键名称 - > JSON

"record": {
        "<Dynamic record name String>": {
          "value": { 
          ....
          }
      }
 }     

因此,动态记录名称String可以是&#34; abcd&#34;,&#34; xyz&#34;或任何其他字符串值。如何定义我的&#34;记录&#34; POJO有这样的钥匙吗?

2 个答案:

答案 0 :(得分:2)

不幸的是,您不能在Java类中使用动态字段(与其他语言不同),因此您有两种选择:

  1. 使用Map s
  2. 使用JSON对象(例如杰克逊的JsonNode
  3. 假设您有这样的数据:

    {
        "record": {
            "jon-skeet": {
                "name": "Jon Skeet",
                "rep": 982706
            },
            "darin-dimitrov": {
                "name": "Darin Dimitrov",
                "rep": 762173
            },
            "novice-user": {
                "name": "Novice User",
                "rep": 766
            }
        }
    }
    

    创建两个类来捕获它,一个用于用户,另一个用于对象本身:

    User.java

    public class User {
        private String name;
        private Long rep;
    
        public String getName() { return name; }
    
        public void setName(String name) { this.name = name; }
    
        public Long getRep() { return rep; }
    
        public void setRep(Long rep) { this.rep = rep; }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", rep=" + rep +
                    '}';
        }
    }
    

    Data.java

    public class Data {
        private Map<String, User> record;
    
        public Map<String, User> getRecord() { return record; }
    
        public void setRecord(Map<String, User> record) { this.record = record; }
    
        @Override
        public String toString() {
            return "Data{" +
                    "record=" + record +
                    '}';
        }
    }
    

    现在,解析JSON(我假设在类路径的根目录中有一个data.json文件):

    public class App {
        public static void main(String[] args) throws Exception {
            final ObjectMapper objectMapper = new ObjectMapper();
    
            System.out.println(objectMapper.readValue(App.class.getResourceAsStream("/data.json"), Data.class));
            System.out.println(objectMapper.readTree(App.class.getResourceAsStream("/data.json")));
        }
    }
    

    这将输出:

    Data{record={jon-skeet=User{name='Jon Skeet', rep=982706}, darin-dimitrov=User{name='Darin Dimitrov', rep=762173}, novice-user=User{name='Novice User', rep=766}}}
    {"record":{"jon-skeet":{"name":"Jon Skeet","rep":982706},"darin-dimitrov":{"name":"Darin Dimitrov","rep":762173},"novice-user":{"name":"Novice User","rep":766}}}
    

    如果是Map,您可以使用一些静态类,例如User,或者使用Map Map s Map<String, Map<String, ...>>完全动态{1}}。但是,如果您发现自己使用了太多地图,请考虑切换到JsonNode s。基本上,它们与Map和“发明”相同,专门用于高动态数据。你以后会很难与他们合作......

    看一个完整的例子,我已经为你准备了here

答案 1 :(得分:0)

这是在Kotlin,但我找到了使用Jackson解决同样问题的方法。

你不需要根节点“记录”,所以你需要摆脱它或者更深入地开始一个节点(你自己就在那里)但是要转换他们孩子的记录列表将id放入对象中具有id的记录列表中:

    val node = ObjectMapper().reader().readTree(json)

    val recordList = mutableListOf<Record>()
    node.fields().iterator().forEach {
        val record = record(
                it.key,
                it.value.get("name").asText(),
                it.value.get("rep").asText()
        )

        recordList.add(event)
    }

node.fields()返回子映射(也是映射)

迭代父地图,你将从密钥中获取id,然后嵌套数据在值中(这是另一个地图)

每个字段的子项都是键:值

key = record id
value = nested data (map)

此解决方案,您不需要多个类来反序列化类列表。