skip to Main Content

I have a JSON response which looks like…

{
  "profile": {
    "userData": {
      "338282892": [
        {
          "userIdentifier": "98shdub777hsjjsuj23",
          "detail": "Test User DEV",
          "type": "customer"
        }
      ]
    }
  }
}

I have created a model, let’s call it UserProfileModel.java. The model has properties using JSON to Java POJO converter, however when doing

UserProfileModel model = objectMapper.readValue(body, UserProfileModel.class);

I am getting below exception because the key user "338282892" because it can not be stored as variabale, for this case I tried to create map

Map<String, List<UserPropertiesModel>>

Here UserPropertiesModel is storing the userIdentifier, detail and type.

 com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "338282892"

I want to know if there is a way to deserialise this kind of JSON using object mapper such that I can do "object.getUserIdentifier()" or "object.getType()".

2

Answers


  1. Yes there is a way, with the use of a custom deserializer. Basically what you want to do is override the default behavior for deserializing a UserData object. Here’s the deserializer definition:

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class UserDataDeserializer extends JsonDeserializer<UserData>{
        @Override
        public UserData deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            List<List<UserDataContent>> output = new ArrayList<>();
            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonNode = p.getCodec().readTree(p);
            Iterator<JsonNode> iterator = jsonNode.elements();
            while(iterator.hasNext()) {
                JsonNode value = iterator.next();
                System.out.println(value);
                List<UserDataContent> obj = mapper.convertValue(value, new TypeReference<List<UserDataContent>>() {});
                output.add(obj);
            }
            UserData returnVal = new UserData();
            returnVal.setUserDataContent(output);
            return returnVal;
        }
    }
    

    And here’s how you would use it:

    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(UserData.class, new UserDataDeserializer());
    mapper.registerModule(module); 
    UserProfileModel model = mapper.readValue(body, UserProfileModel.class);
    

    Here is a github repository with a complete working example.

    Login or Signup to reply.
  2. You can not model without having a valid "key" (which should be a string for mapping in a POJO class)

    Alternatively, you can use a Map<String, Object> for traversing to the inner JSON blob.

    Understand this,

    Top layer is "profile" and anything as value to profile is value for map.

    So you have a Map<"Profile" (a String), Object (whatever value profile has)> map1.

    Then you do same for inner layer of "userData", so basically the object you stored in map1 is now again a Map<String, Object> map2 and same for deeper. layers.

    This might not be the best approach but there is no way you can serialise this type of JSON using Mirconaut or Lombok or Spring.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search