How deserialize json object array as array of json strings?

后端 未结 1 1471
半阙折子戏
半阙折子戏 2021-01-22 18:57

Consider json input:

{
    companies: [
        {
            \"id\": 1,
            \"name\": \"name1\"
        },
        {
            \"id\": 1,
                     


        
相关标签:
1条回答
  • 2021-01-22 19:22

    There is no annotation-only solution for your problem. Somehow you have to convert JSON Object to java.lang.String and you need to specify that conversion.

    You can:

    1. Write custom deserializer which is probably most obvious solution but forbidden in question.
    2. Register custom com.fasterxml.jackson.databind.deser.DeserializationProblemHandler and handle com.fasterxml.jackson.databind.exc.MismatchedInputException situation in more sophisticated way.
    3. Implement com.fasterxml.jackson.databind.util.Converter interface and convert JsonNode to String. It is semi-annotational way to solve a problem but we do not implement the worst part - deserialisation.

    Let's go to point 2. right away.

    2. DeserializationProblemHandler

    Solution is pretty simple:

    ObjectMapper mapper = new ObjectMapper();
    mapper.addHandler(new DeserializationProblemHandler() {
        @Override
        public Object handleUnexpectedToken(DeserializationContext ctxt, JavaType targetType, JsonToken t, JsonParser p, String failureMsg) throws IOException {
            if (targetType.getRawClass() == String.class) {
                // read as tree and convert to String
                return p.readValueAsTree().toString();
            }
            return super.handleUnexpectedToken(ctxt, targetType, t, p, failureMsg);
        }
    });
    

    Read a whole piece of JSON as TreeNode and convert it to String using toString method. Helpfully, toString generates valid JSON. Downside, this solution has a global scope for given ObjectMapper instance.

    3. Custom Converter

    This solution requires to implement com.fasterxml.jackson.databind.util.Converter interface which converts com.fasterxml.jackson.databind.JsonNode to String:

    class JsonNode2StringConverter implements Converter<JsonNode, String> {
        @Override
        public String convert(JsonNode value) {
            return value.toString();
        }
    
        @Override
        public JavaType getInputType(TypeFactory typeFactory) {
            return typeFactory.constructType(new TypeReference<JsonNode>() {
            });
        }
    
        @Override
        public JavaType getOutputType(TypeFactory typeFactory) {
            return typeFactory.constructType(new TypeReference<String>() {
            });
        }
    }
    

    and now, you can use annotation like below:

    @JsonDeserialize(contentConverter = JsonNode2StringConverter.class)
    private List<String> companies;
    

    Solutions 2. and 3. solve this problem almost in the same way - read node and convert it back to JSON, but uses different approaches.

    If, you want to avoid deserialising and serialising process you can take a look on solution provided in this article: Deserializing JSON property as String with Jackson and take a look at:

    • How to serialize JSON with array field to object with String field?
    • How to get a part of JSON as a plain text using Jackson
    • How to extract part of the original text from JSON with Jackson?
    0 讨论(0)
提交回复
热议问题