简体   繁体   English

Jackson JSON密钥作为Java中的值

[英]Jackson JSON key as value in Java

I'm using Jackson in Spring MVC application. 我在Spring MVC应用程序中使用Jackson。 I want to use a String value as key name for Java POJO --> JSON 我想使用String值作为Java POJO-> JSON的键名

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

So the dynamic record name String could be "abcd","xyz" or any other string value. 因此,动态记录名称String可以是“ abcd”,“ xyz”或任何其他字符串值。 How can I define my "record" POJO to have a key like that ? 如何定义我的“记录” POJO以具有这样的键?

Unfortunately, you cannot have dynamic fields in Java classes (unlike some other languages), so you have two choices: 不幸的是,您不能在Java类中拥有动态字段(与某些其他语言不同),因此您有两种选择:

  1. Using Map s 使用Map
  2. Using JSON objects (ie JsonNode in case of Jackson) 使用JSON对象( JsonNode在Jackson的情况下为JsonNode

Suppose, you have a data like this: 假设您有一个像这样的数据:

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

Create two classes to capture it, one for user and another for the object itself: 创建两个类来捕获它,一个用于用户,另一个用于对象本身:

User.java : 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 : 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 +
                '}';
    }
}

Now, parse the JSON (I assume there is a data.json file in the root of your classpath): 现在,解析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")));
    }
}

This will output: 这将输出:

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}}}

In case of a Map you can use some static classes, like User in this case, or go completely dynamic by using Map s of Map s ( Map<String, Map<String, ...>> . However, if you find yourself using too much maps, consider switching to JsonNode s. Basically, they are the same as Map and "invented" specifically for highly dynamic data. Though, you'll have some hard time working with them later... 如果是Map ,则可以使用一些静态类,例如User在这种情况下),或者通过使用MapMapMap<String, Map<String, ...>>完全变为动态类。但是,如果您发现自己使用过多的地图,请考虑切换到JsonNode 。基本上,它们与Map相同,并且专门针对高度动态的数据“发明”。尽管如此,稍后您将很难使用它们。

Take a look at a complete example, I've prepared for you here . 看一个完整的例子,我已经在这里为您准备了。

This is in Kotlin but I have found a solution to the same problem using Jackson. 这是在Kotlin,但我已经找到了使用Jackson来解决相同问题的解决方案。

You don't need the root node "record", so you will need to get rid of it or start one node deeper(you're on your own there) but to turn the list of records that are children of their id into a list of records with id in the object follows: 您不需要根节点“ record”,因此您需要摆脱它或更深地开始一个节点(您自己位于那里),但要将属于其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() returns a map of children(also maps) node.fields()返回孩子的地图(也有地图)

iterating through the parent map you will get the id from the key and then the nested data is in the value (which is another map) 遍历父映射,您将从键获取ID,然后嵌套数据在值中(这是另一幅映射)

each child of fields is key : value where 每个字段的子项都是key:value where

key = record id
value = nested data (map)

This solution, you don't need multiple classes to deserialize a list of classes. 使用此解决方案,您不需要多个类来反序列化类列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM