Search code examples
javajsonjacksonobjectmapper

Parse Json into POJO using Jackson


I have the following json

{
    "root": {
        "status": "UP",
        "connection1": {
            "status": "UP"
        },
        "connection2": {
            "status": "UP"
        }
    }
}

Also i have the following POJO classes i want to convert JSON into

@JsonIgnoreProperties(ignoreUnknown = true)
public class POJO {

    @JsonProperty("root")
    @JsonDeserialize(using = RootDeserializer.class)
    private Root root;

    //getters + setters
}

public class Root {

    private boolean isAlive;
    private List<Connection> connections;

    public Root(boolean isAlive, List<Connection> connections) {
        this.isAlive = isAlive;
        this.connections = connections;
    }

    //getters + setters
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class Connection {

    private String status;

    //getters + setters
}

And finally i have this deserializer to convert json into Root instance

public class RootDeserializer extends JsonDeserializer<Root> {

    private static final String CONNECTION_PREFIX = "connection";
    private static final String UP_STATUS = "UP";

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Root deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        Map<String, Map<String, Object>> rootJsonMap = parser.readValueAs(Map.class);

        boolean isAlive = StringUtils.equals(UP_STATUS, String.valueOf(rootJsonMap.get("status")));
        List<Connection> connections = rootJsonMap.entrySet()
                .stream()
                .filter(entry -> StringUtils.startsWithIgnoreCase(entry.getKey(), CONNECTION_PREFIX))
                .map(this::mapToConnection)
                .collect(Collectors.toList());

        return new Root(isAlive, connections);
    }

    private PosServerConnection mapToConnection(Map.Entry<String, Map<String, Object>> entry) {
        Map<String, Object> connectionJsonMap = entry.getValue();
        return objectMapper.convertValue(connectionJsonMap, Connection.class);
    }
}

This way i can group all my Connections into one List in Root class. My question is there any another way to do this ??

I'd like to do this without such big deserializer using just Jackson annotations on my Pojo classes


Solution

  • You can simply achieve this by using @JsonAnySetter annotation for customizing Setter for List<Connection> as follows. You can also reference to Jackson Annotation Examples to see how it works.

    POJOs

    public class Pojo {
        private Root root;
    
        //general getters, setters and toString
    }
    
    public class Root {
        private String status;
        private List<Connection> connections = new ArrayList<>();
    
        public List<Connection> getConnections() {
            return connections;
        }
    
        @JsonAnySetter
        public void setConnections(String name, Connection connection) {
            connection.setName(name);
            this.connections.add(connection);
        }
    
        //other getters, setters and toString
    }
    
    public class Connection {
        private String name;
        private String status;
    
        //general getters, setters and toString
    }
    

    Then you can serialize the given JSON string to Pojo with common way by Jackson:

    Code Snippet

    ObjectMapper mapper = new ObjectMapper();
    Pojo pojo = mapper.readValue(jsonStr, Pojo.class);
    System.out.println(pojo.getRoot().getConnections().toString());
    

    Console output

    [Connection [name=connection1, status=UP], Connection [name=connection2, status=UP]]