1

I have below classes:

public class Result<T> {
    public int code;
    public Object meta;
    public T data;
}

public class User {
    public int id;
    public String name;
}

public class Error {
    public String field;
    public String message;
}

I want to deserialize a JSON payload based on code field. If code >= 10, return Result<ArrayList<Error>>, otherwise return Result<User>

Currently, I map JSON to Result<Object> first, then check the code field. Based on that value I make second map to desired object.

ObjectMapper mapper = new ObjectMapper();
Result<Object> tempResult = mapper.readValue(json, new TypeReference<Result<Object>>() {});

if (tempResult.code < 10) {    
    Result<User> result = mapper.readValue(json, new TypeReference<Result<User>>() {});
    return result;
} else {
    Result<ArrayList<Error>> result = mapper.readValue(json, new TypeReference<Result<ArrayList<Error>>>() {});
    return result;
}

Is there an elegant way to do this without deserializing it 2 times?

1 Answer 1

1

You need to implement custom TypeIdResolver:

class UserTypeIdResolverBase extends TypeIdResolverBase {

    @Override
    public String idFromValue(Object value) {
        throw new IllegalStateException("Not implemented!");
    }

    @Override
    public String idFromValueAndType(Object value, Class<?> suggestedType) {
        throw new IllegalStateException("Not implemented!");
    }

    @Override
    public JsonTypeInfo.Id getMechanism() {
        return JsonTypeInfo.Id.CUSTOM;
    }

    @Override
    public JavaType typeFromId(DatabindContext context, String id) {
        if (Integer.parseInt(id) < 10) {
            return context.getTypeFactory().constructType(new TypeReference<Result<User>>() {});
        }
        return context.getTypeFactory().constructType(new TypeReference<Result<List<Error>>>() {});
    }
}

and declare it for a Result class:

@JsonTypeInfo(property = "code", use = JsonTypeInfo.Id.CUSTOM, visible = true)
@JsonTypeIdResolver(UserTypeIdResolverBase.class)
class Result<T>
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.