【问题标题】:Jackson JSON map key as property of contained objectJackson JSON 映射键作为包含对象的属性
【发布时间】:2017-11-02 13:16:45
【问题描述】:

给定这样的结构:

{
  "nameOfObject": { "score": 100 },
  "anotherObject": { "score": 30 }
}

是否可以将其映射到:

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

class ScoreKeeper {
  String name;
  int score;
}

所以您最终会将ScoreKeeper 实例的name 属性分别设置为"nameOfObject""anotherObject"

【问题讨论】:

  • 您可能需要创建一个中间对象来序列化为 ,然后可以将其转换为您想要的表示形式。

标签: java json jackson


【解决方案1】:

我坚信将 POJO 与外部化分开。将您的 JSON 读入 Map,然后像这样构建您的 Container/ScoreKeeper 对象(任何拼写错误的 apols):

mapper = new ObjectMapper();

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

Container c = new Container();

for(Map.Entry<String, Object> me : data.entrySet()) {
    String key = me.getKey();
    Map info = (Map) me.getValue();

    ScoreKeeper sk = new ScoreKeeper();
    sk.setName(key);
    Integer q = info.get("score");
    sk.setScore(q);

    c.put(key, sk);
}

【讨论】:

  • 当然。我实际上只是在寻找一种简洁的方法来反序列化现有的 API。不过感谢您的建议。
【解决方案2】:

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

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

【讨论】:

  • 我无法让这种方法与请求的 JSON 一起工作(在原始问题中),这种方法只有在根节点包含“nameOfObject”和“anotherObject”时才有效
【解决方案3】:

这是 @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);
}

【讨论】:

    猜你喜欢
    • 2017-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    相关资源
    最近更新 更多