Java Jackson JSON映射键作为包含对象的属性

Java Jackson JSON映射键作为包含对象的属性,java,json,jackson,Java,Json,Jackson,考虑到这样的结构: { "nameOfObject": { "score": 100 }, "anotherObject": { "score": 30 } } 是否可以将此映射到: class Container { Map<String, ScoreKeeper> scoreKeepers; } class ScoreKeeper { String name; int score; } 类容器{ 地图计分员; } 班级记分员{ 字符串名; 智力得分; }

考虑到这样的结构:

{
  "nameOfObject": { "score": 100 },
  "anotherObject": { "score": 30 }
}
是否可以将此映射到:

class Container {
  Map<String, ScoreKeeper> scoreKeepers;
}

class ScoreKeeper {
  String name;
  int score;
}
类容器{
地图计分员;
}
班级记分员{
字符串名;
智力得分;
}

因此,您最终将
记分员
实例的
name
属性分别设置为
“nameOfObject”
“anotherObject”

我坚信将您的POJO与外部化分开。将JSON读入地图,然后像这样构建容器/记分员对象(对于任何拼写错误,请使用APLOS):

mapper=newObjectMapper();
Map data=mapper.readValue(inputstream,Map.class);
容器c=新容器();
对于(Map.Entry me:data.entrySet()){
String key=me.getKey();
Map info=(Map)me.getValue();
记分员sk=新记分员();
sk.setName(key);
整数q=信息获取(“分数”);
sk.setScore(q);
c、 put(键,sk);
}

替代解决方案,其中通过使用自定义反序列化器在值对象上设置键
名称

@Test
public void test() throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();

    Data data = mapper.readValue("{\"users\": {\"John\": {\"id\": 20}, \"Pete\": {\"id\": 30}}}", Data.class);

    assertEquals(20, data.users.get("John").id);
    assertEquals(30, data.users.get("Pete").id);
    assertEquals("John", data.users.get("John").name);
    assertEquals("Pete", data.users.get("Pete").name);
}

public static class Data {
    @JsonDeserialize(contentUsing = Deser.class)
    public Map<String, User> users;
}

public static class User {
    public String name;
    public int id;
}

public static class Deser extends JsonDeserializer<User> {

    @Override
    public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String name = ctxt.getParser().getCurrentName();

        User user = p.readValueAs(User.class);

        user.name = name;  // This copies the key name to the value object

        return user;
    }
}
@测试
public void test()抛出JsonParseException、JsonMappingException、IOException{
ObjectMapper mapper=新的ObjectMapper();
Data Data=mapper.readValue(“{\'users\':{\'John\':{\'id\':20},\'Pete\':{\'id\':30}}}”,Data.class);
assertEquals(20,data.users.get(“John”).id);
assertEquals(30,data.users.get(“Pete”).id);
assertEquals(“John”,data.users.get(“John”).name);
assertEquals(“Pete”,data.users.get(“Pete”).name);
}
公共静态类数据{
@JsonDeserialize(contentUsing=desr.class)
公众地图使用者;
}
公共静态类用户{
公共字符串名称;
公共int id;
}
公共静态类Deser扩展JsonDeserializer{
@凌驾
公共用户反序列化(JsonParser p,DeserializationContext ctxt)抛出IOException,JsonProcessingException{
字符串名称=ctxt.getParser().getCurrentName();
User User=p.readValueAs(User.class);
user.name=name;//将键名复制到值对象
返回用户;
}
}

这是@Buzz Moschetti的一个改进版本,它使用Jackson的ObjectMapper.convertValue()来处理属性解析

ObjectMapper mapper = new ObjectMapper();

Map<String,Object> data = mapper.readValue(inputstream, Map.class);

Container c = new Container();

for(Map.Entry<String, Object> entry : data.entrySet()) {
    String name = entry.getKey();
    ScoreKeeper sk = mapper.convertValue(entry.getValue(), ScoreKeeper.class);
    sk.name = name;
    c.scoreKeepers.put(name, sk);
}
ObjectMapper mapper=new ObjectMapper();
Map data=mapper.readValue(inputstream,Map.class);
容器c=新容器();
for(Map.Entry:data.entrySet()){
字符串名称=entry.getKey();
ScoreKeeper sk=mapper.convertValue(entry.getValue(),ScoreKeeper.class);
sk.name=名称;
c、 记分员。put(姓名,sk);
}

您可能需要创建一个要序列化的中间对象,然后可以将其转换为所需的表示形式。确定。我实际上只是在寻找一种简洁的方法来反序列化现有的API。不过,谢谢你的建议。我无法使用这种方法来处理请求的JSON(在原始问题中),这种方法只有在根节点包含“nameOfObject”和“anotherObject”时才有效
ObjectMapper mapper = new ObjectMapper();

Map<String,Object> data = mapper.readValue(inputstream, Map.class);

Container c = new Container();

for(Map.Entry<String, Object> entry : data.entrySet()) {
    String name = entry.getKey();
    ScoreKeeper sk = mapper.convertValue(entry.getValue(), ScoreKeeper.class);
    sk.name = name;
    c.scoreKeepers.put(name, sk);
}