2

Consider json input:

{
    companies: [
        {
            "id": 1,
            "name": "name1"
        },
        {
            "id": 1,
            "name": "name1"
        }
    ],
    nextPage: 2
}

How deserialize this into class:

public class MyClass {
    List<String> companies;
    Integer nextPage;
}

Where List<String> companies; consists of strings:

{"id": 1,"name": "name1"}
{"id": 1,"name": "name1"}

@JsonRawValue doesn't work for List<String> companies;

Is there a way to configure Jackson serialization to keep companies array with raw json string with annotations only? (E.g. without writing custom deserializator)

1
  • Have you fixed this problem? Did my answer was helpful? Commented Jul 14, 2020 at 9:24

1 Answer 1

0

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:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.