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