Java 如何通过Jackson反序列化将每个映射项的键注入到相应的值对象中?

Java 如何通过Jackson反序列化将每个映射项的键注入到相应的值对象中?,java,json,jackson,Java,Json,Jackson,我有以下json对象 { "items": { "item-1": {"type":"A", "desc": "blabla"}, "item-2": {"type":"B", "desc": "blabla"}, ... } } { "items": { "item-1": {"id":"item-1", "type":"A", "desc": "blabla"}, "item-2": {"id":"item-2", "type":"B",

我有以下json对象

{
  "items": {
    "item-1": {"type":"A", "desc": "blabla"},
    "item-2": {"type":"B", "desc": "blabla"},
    ...
  }
}
{
  "items": {
    "item-1": {"id":"item-1", "type":"A", "desc": "blabla"},
    "item-2": {"id":"item-2", "type":"B", "desc": "blabla"},
    ...
  }
}
我想把这个json对象映射到下面的java对象

public class MyObject {
  private final Map<String,Item> items;

  @JsonCreator
  public MyObject(@JsonProperty Map<String,Item> items) { ... }
  ...
}

class Item {
  private final string id;             <-- ideally could be initialized by the corresponding key in the map
  private final String type;
  private final String desc;

  public Item(@JsonProperty String id, @JsonProperty String type, @JsonProperty String desc) { ... }
}
这并不理想(即:冗余->易出错)

是否有一个jackson注释来解决这个常见模式,或者其他方法?我找不到类似
@JsonProperty(useKeyMap=true)
的内容

更新:我对构造函数的id参数初始化为null的解决方案不感兴趣

我已经尝试了您的示例,您还需要在Items类构造函数上添加@Json creator注释。
I have tried your example you need to put @Json creator annotation on your Items class constructor as well.

Below is the modified code.

class Item {

    private final String id;

    private final String type;

    private final String desc;

    @JsonCreator
    public Item( @JsonProperty("id")String id,   @JsonProperty("type")String type,  @JsonProperty("desc")String desc) {
        this.id = id;
        this.type = type;
        this.desc = desc;
    }
}

class MyObject {
    private final Map<String,Item> items;

    @JsonCreator
    public MyObject(@JsonProperty("items") Map<String, Item> items) {
        this.items = items;
    }
下面是修改后的代码。 类项目{ 私有最终字符串id; 私有最终字符串类型; 私有最终字符串描述; @JsonCreator 公共项(@JsonProperty(“id”)字符串id、@JsonProperty(“type”)字符串类型、@JsonProperty(“desc”)字符串desc){ this.id=id; this.type=type; this.desc=desc; } } 类MyObject{ 私人最终地图项目; @JsonCreator 公共MyObject(@JsonProperty(“项”)映射项){ 这个项目=项目; }

它反序列化json,如果您不提供id值,则默认值为null。

我找到了一个解决方案,其中包括一个自定义反序列化器。这里没有真正的魔力(没有方便的注释),但它可能会有所帮助

@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;   // Fills the key in 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;//填充值对象中的键!
返回用户;
}
}

是的,我知道这是默认行为,我的问题更多的是在json对象中未提供id属性时,避免Item类的构造函数中出现此空id。顺便说一下,如果使用编译器选项-parameters(javac)您不需要在构造函数中指定每个参数的名称。然后使用@JsonCreator实际上会帮助您这样做:`@JsonCreator公共项(@JsonProperty(“type”)字符串类型,@JsonProperty(“desc”)字符串描述){//this.id=id;this.type=type;this.desc=desc;}`