Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skip the first level in JSON when using jackson

Tags:

java

json

jackson

The JSON object I'm receiving is like this.

{  
   "Question279":{  
      "ID":"1",
      "Contents":"Some texts here",
      "User":"John",
      "Date":"2016-10-01"
}

I need to map the JSON to the following java bean.

public class Question {
    @JsonProperty("ID")
    private String id;

    @JsonProperty("Contents")
    private String contents;

    @JsonProperty("User")
    private String user;

    @JsonProperty("Date")
    private LocalDate date;

    //some getters and setters are skipped...
}

Also notice that the first level in the above JSON object Question279 is not always the same, it depends on the parameter user provided to obtain the JSON. And I cannot change the situation.

Currently I'm using something like this.

ObjectMapper mapper = new ObjectMapper();
String json = "{'Question279':{'ID':'1', 'Contents':'Some texts here', 'User':'John', 'Date':'2016-10-01'}"
Question question = mapper.readValue(json, Question.class);

But it's not working, of course, I got a Question class full of null. How to make it work in this case?

like image 488
Searene Avatar asked Feb 20 '17 10:02

Searene


3 Answers

Try this can be any help

ObjectMapper mapper = new ObjectMapper();

String json = "{\"Question279\":{\"ID\":\"1\", \"Contents\":\"Some texts here\", \"User\":\"John\", \"Date\":\"2016-10-01\"}}";

mapper.readTree( json ).fields().forEachRemaining( arg -> {

    Question question = mapper.convertValue( arg.getValue(), Question.class );

    System.out.println( question.getDate() );
} );

** As there is no default conversion from String to LocalDate I changed LocalDate date to String date in Question.java

like image 76
Ravi MCA Avatar answered Oct 18 '22 11:10

Ravi MCA


I recommend having your ObjectMapper create a specialized ObjectReader for each case:

String questionKey = "Question279"; // Generate based on parameter used to obtain the json
ObjectReader reader = mapper.reader().withRootName(questionKey).forType(Question.class);
Question q = reader.readValue(json);
... // Work with question instance
like image 31
Henrik Aasted Sørensen Avatar answered Oct 18 '22 09:10

Henrik Aasted Sørensen


Your JSON defines a map of collections, so you could parse it that way:

ObjectMapper mapper = new ObjectMapper();
Map<String, Question> questions = mapper.readValue(json,
    new TypeReference<Map<String, Question>>(){});
Question question = questions.get("Question279");

The new TypeReference<Map<String, Question>>(){} defines an anonymous class extending TypeReference<Map<String, Question>>. Its only purpose is to tell Jackson that it should parse the JSON as a map of String->Question pairs. After parsing the JSON, you'll need to extract the question that you want from the map.

like image 38
Kenster Avatar answered Oct 18 '22 09:10

Kenster