简体   繁体   中英

How to convert a map which value is a JSON String to an object?

I'm convertting a map to object, but some values of the map are Json String, I tried to convert it using jackson like the code below but failed.

public class Father {
    private String name;
    private List<Child> children;

}

public class Child {
    private String name;
}

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        String s= JSON.toJSONString(Arrays.asList(new Child("Bob"),new Child("Jackson")));
        Map<String,String> map=new HashMap();
        map.put("name","Jack")
        map.put("children",s);

// how to convert the map to a Father Object?
//this does not work
 ObjectMapper mapper = new ObjectMapper();
 mapper.convertValue(map, Father.class);

}

edit: here is the exception:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot deserialize instance of `java.util.ArrayList` out of VALUE_STRING token
 at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: model.Father["children"])
    at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3750)
    at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:3668)
    at service.BasicBehavior.main(BasicBehavior.java:25)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of VALUE_STRING token
 at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: model.Father["children"])
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1139)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1093)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:332)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:265)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3745)
    ... 2 more

If you use customdeserializer to serialize your class and it will be ok. The problem is that you cannot convert your Child class.

public class CustomStringDeserializer extends JsonDeserializer<List<Child>> {

@Override
public List<Child> deserialize(JsonParser parser, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
    List<Child> ret = new ArrayList<>();

    ObjectCodec codec = parser.getCodec();
    ObjectMapper mapper = new ObjectMapper();
    TreeNode node = codec.readTree(parser);

    if (node.isArray()){
        for (JsonNode n : (ArrayNode)node){
            ret.add(mapper.convertValue(n, Child.class));
        }
    } else if (node.isValueNode()){
        ret.add(mapper.convertValue(node, Child.class));
    }
    return ret;
   }
}

And of course you should use this deserializer as annotation in the Father class.

 @JsonDeserialize(using = CustomStringDeserializer.class)
 private List<Child> children;

Besides, you should use Map<String, Object> like that

        Map<String,Object> map = new HashMap();
        map.put("name","Jack");
        map.put("children", Arrays.asList(new Child("Bob"),new Child("Jackson")));

After all this changes, it will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM