Java 如何通过Jackson反序列化将每个映射项的键注入到相应的值对象中?
我有以下json对象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",
{
"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;}`