[英]How to inject the key of each map entry into the corresponding value object with Jackson deserialization?
I have the following json object. 我有以下json对象。
{
"items": {
"item-1": {"type":"A", "desc": "blabla"},
"item-2": {"type":"B", "desc": "blabla"},
...
}
}
and I want to map this json object to the following java object. 我想将此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) { ... }
}
The deserialization works only when I provide the following json object. 反序列化仅在我提供以下json对象时才起作用。
{
"items": {
"item-1": {"id":"item-1", "type":"A", "desc": "blabla"},
"item-2": {"id":"item-2", "type":"B", "desc": "blabla"},
...
}
}
That's not ideal (ie: redundancy -> error prone). 这并不理想(即:冗余 - >容易出错)。
Is there a jackson annotation to solve this common pattern, or some other way? 是否有杰克逊注释来解决这种常见模式或其他方式? I failed to find something like
@JsonProperty(useKeyMap=true)
. 我找不到类似
@JsonProperty(useKeyMap=true)
东西@JsonProperty(useKeyMap=true)
。
Update: I'm not interested by a solution where the id argument of the constructor is initialized to null. 更新:我对构造函数的id参数初始化为null的解决方案不感兴趣。
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;
}
It deserialises the json and if you will not provide the value of id then default it would be null. 它反序列化json,如果你不提供id的值,那么默认它将为null。
I have found a solution for this, involving a custom Deserializer. 我找到了一个解决方案,涉及一个自定义反序列化器。 There is no real magic here (no handy annotation), but perhaps it will help.
这里没有真正的魔法(没有方便的注释),但也许它会有所帮助。
@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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.