How would I use Jackson to flatten JSON with nested array? - java

I am using JackSon to parse the following JSON:
{
"AwardID": "1111111",
"AwardTitle": "Test Title",
"Effort":
"[
{
"PersonFirstName": "Jon",
"PersonLastName": "Snow"
}
]"
}
I would like to flatten this to be used in the following class:
public class Award {
private String awardId;
private String awardTitle;
private String personFirstName;
private String personLastName;
}
I have tried the following and have gotten the first two values, but I haven't been able to get the values from Effort trying to use JsonUnwrapped. I noted that it doesn't work with arrays, but I am trying the objectMapper.configure(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS, true) configuration in the main method used to get the values.
public class Award {
#JsonProperty("AwardID")
private String awardId;
#JsonProperty("AwardTitle")
private String awardTitle;
#JsonUnwrapped
private Effort effort;
}
public class Effort {
private String personFirstName;
private String personLastName;
}
Note that I only expect one value in the Effort array from the API response at this time.
What is recommended to try next? Thank you!

The easiest way is having a List<Effort> if you have a JSON Array.
If there is always 1 item for Effort, the returning JSON should not have Effort as a JSON Array and instead should be a JSON Object.
But if you can only handle it codewise, you can have something like this (Note that there should always contain one item in Effort, otherwise it will throw Exception):
public class Award {
#JsonProperty("AwardID")
private String awardId;
#JsonProperty("AwardTitle")
private String awardTitle;
#JsonProperty("Effort")
private Effort effort;
}
public class Effort {
#JsonProperty("PersonFirstName")
private String personFirstName;
#JsonProperty("PersonLastName")
private String personLastName;
}
And your ObjectMapper needs to be enabled with DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS as well:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
Award award = mapper.readValue(rawJson, Award.class); // rawJson is your JSON String
And it should have the following output:
Award(awardId=1111111, awardTitle=Test Title, effort=Effort(personFirstName=Jon, personLastName=Snow))
Note that the annotation #JsonUnwrapped can only apply on JSON Object, not JSON Array:
Value is serialized as JSON Object (can not unwrap JSON arrays using this mechanism)

Related

Json multiple string arrays into multiple Java String list

I am looking for solution to convert my json that contains multiple fields with string arrays and that i need to convert into Java list of string. I am using Jackson to do that.
and below is the request object
public class PullQuestionRequest {
private List<String> classNo;
private List<String> subject;
private List<String> topic;
private List<String> learningElement;
private List<String> complexity;
//and setters and getters for the fields..
and below is my json
{
"classNo": ["7","10"],
"subject": ["Maths","English"],
"topic": ["PS","NS"],
"learningElement": ["PS","ZOOLOGY"],
"complexity" : ["LEVEL 1","LEVEL 2"]
}
below is the code for my controller.
public GetAllQuestionResponse pullQuestions(#RequestParam("data") String questionRequest)
throws IOException {
ObjectMapper Obj = new ObjectMapper();
PullQuestionRequest request = Obj.readValue(questionRequest, PullQuestionRequest.class);
I could be able to convert whole json into java object. I need a help How to pull the string arrays for ClassNo , subject and others as List of strings in java.

Parse JSON without object name in Java

I am trying to parse this JSON which is coming as the response to a REST API call. Can you please help me parsing it as key value pairs?
The object names are not present. There is nesting as well. There seems to be no new line between records.
The aim is to extract this data and load it into a database.
[
{
"cc_emails":["feedback#xyz.com"],
"fwd_emails":[],
"reply_cc_emails":["feedback#xyz.com"],
"fr_escalated":false,
"spam":false,
"email_config_id":6000038087,
"group_id":6000110481,
"priority":1,
"requester_id":6010410791,
"responder_id":6002817857,
"source":1,
"company_id":null,
"status":2,
"subject":"fare",
"to_emails":["feedback#xyz.com"],
"product_id":null,
"id":45043,
"type":null,
"due_by":"2016-03-12T08:58:02Z",
"fr_due_by":"2016-03-08T08:58:02Z",
"is_escalated":false,
"description":"Dear xyze Team,\r\n\r\nWhy r u increased fair again and againasas0mail.gmail.com</a>.<br>\n",
"custom_fields":
{
"category":null,
"issue":null,
"route_id":null,
"phone_number":null,
"department":null,
"booking_id":null
},
"created_at":"2016-03-07T08:58:02Z",
"updated_at":"2016-03-07T08:58:03Z",
// ...... repeat
}
]
The best way to do this would be to use http://www.jsonschema2pojo.org/
Enter your json there
Change source type to JSON
set the correct class name and package.
The resulting pojo can be directly mapped from the json
If you are using resttemplate to hit the api then you can use getForObject to automatically set the pojo from the output.
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#getForObject-java.lang.String-java.lang.Class-java.lang.Object...-
Using gson you can do this quite simply.
Do a class to match the fields in the json something like:
public class Example {
private List<String> cc_emails;
private List<String> fwd_emails;
private List<String> reply_cc_emails;
private Boolean fr_escalated;
private Boolean spam;
private Integer email_config_id;
...
private CustomFields custom_fields;
private String created_at;
private String updated_at;
}
Then you need to do another to map the custom fields
public class CustomFields {
private String category;
...
}
And using json you can parse it like this:
Type type = new TypeToken<Collection<Example>>(){}.getType();
new Gson().fromJson(json,type);
You have to exaplain to Gson it's a list, if it was a single object it would be this:
new Gson().fromJson(json,Example.class);
This is the aproach I usually take, also in the dates java.sql.Timestamp class might also parse it, you would need to try it though.
You can use Gson (https://github.com/google/gson) or Jackson (https://github.com/FasterXML/jackson) and deserialize it to a Map.

gson JSON to Java -- json property has . or - in it

What steps will reproduce the problem?
1.I have a json reponse as
String Content =
"{
"region":{
"state.code":"TX",
"country-code":"USA"
}
}";
2.I want to convert this Json Object into Java Object.I have this Java class to convert
public class Region{
private String stateCode;
private String countryCode;
public String getStateCode ()
{
return stateCode;
}
public void setStateCode (String stateCode)
{
this.stateCode = stateCode;
}
public String getCountryCode ()
{
return countryCode;
}
public void setCountryCode (String countryCode)
{
this.countryCode = countryCode;
}
}
3.My problem is Java doesnt allow . or - in variable name.Which doesnt allow json string to map to Region java class object giving null .
gson.fromJson(Content, Region.class);
What is the expected output? What do you see instead?
Can anybody please help me in this?
I have tried #SerializedName annotations but it is not working.
What version of the product are you using? On what operating system?
Please provide any additional information below.
You're trying to map this JSON
{
"region":{
"state.code":"TX",
"country-code":"USA"
}
}
to an instance of type Region. That JSON is a JSON Object which contains a pair with name region and a value which is a JSON Object. That JSON Object has two pairs, one with name state.code and JSON String value TX and one with name country-code and JSON String value USA.
You can't map that to a Region object. You have to bypass the root's pair named region.
Create a encapsulating type
class RegionContainer {
private Region region;
// the rest
}
and map that
gson.fromJson(Content, RegionContainer.class);
#SerializedName will work for your fields.
#SerializedName("state.code")
private String stateCode;

JSON string serialization ( to camel case ) and deserialization (from snake case )using Jackson

I am trying to deserialize a json string to POJO and then serialize it back to json string using Jackson, but in this process I want resultant json string to have changed key values.
e.g. input json string:
{"some_key":"value"}
here is what my POJO looks like
public class Sample {
#JsonProperty("some_key")
private String someKey;
public String getSomeKey(){
return someKey ;
};
}
When I serialize it again I want json string to be something like this
{"someKey":"value"} .
Is there any way I can achieve this?
I was able to do deserialization by renaming setter functions according to what is the input json string .
class Test{
private String someKey;
// for deserializing from field "some_key"
public void setSome_key( String someKey) {
this.someKey = someKey;
}
public String getSomeKey(){
return someKey;
}
}
You should be able to pull this off by defining a creator for deserialization and then let Jackson do its default behavior for serialization.
public class Sample {
private final String someKey;
#JsonCreator
public Sample(#JsonProperty("some_key") String someKey) {
this.someKey = someKey;
}
// Should serialize as "someKey" by default
public String getSomeKey(){
return someKey;
}
}
You may need to disable MapperFeature.AUTO_DETECT_CREATORS on your ObjectMapper for this to work.

"Dotting" in JSON using Gson on Android

I'm trying to parse a JSON feed using Gson in Android. I know the JSON is valid. I suspect that it is because the format is like this:
"Info":[
{
"Id":"",
"Name":"",
"Description":"",
"Date":""
}
In order to parse this I need to "dot" in. Ex: Info.Name
How can I do this in a serialized DTO?
#SerializedName("Name")
public String name;
#SerializedName("Description")
public String desc;
#SerializedName("Date")
public String date;
I tried to put "Info." in front of each serializedName but that didn't work either. I also know my JSON parsing method works properly, because it's used somewhere else with a different DTO. But in that parsing, I don't have to "dotting" issue.
Can anyone help?
EDIT: I have tried everything you guys posted, and nothing works. The error says:
The JsonDeserializer failed to deserialize json object {"Info":[{".......
SECOND EDIT:
I was able to get rid of the error, but now it returns null. Haha, getting pretty damn frustrated right about now!
I am assuming that the actual JSON you are intaking is valid because the example you provided is not. In your JSON example, you have "Info":[ but there is no outer object containing the "Info" property, which is a must. The valid JSON would be:
{
"Info": [
{
"Id":"",
"Name":"",
"Description":"",
"Date":"",
}
]
}
This is a JSON object that has a property "Info" which has a value that is a list of objects. This list of objects contains one object that has the properties "Id", "Name", "Description", and "Date", all of which have empty-string values.
Here is a quick tutorial on how to use GSON to parse a JSON feed such as the above JSON:
You will need a class to represent the items in the list:
public class InfoItem {
public String Id;
public String Name;
public String Description;
public String Date;
public InfoItem() {}
}
And one to represent the list of Items:
public class InfoItemList extends LinkedList<InfoItem> {
public InfoItemList() { super() };
}
This added complexity is because GSON cannot otherwise get the type of a generic collection from the class data.
And one to represent the overall JSON message:
public class InfoMessage {
public InfoItemList Info;
public InfoMessage() {};
}
And then just:
gson.fromJson(jsonString, InfoMessage.getClass());
If just de-serializing a collection:
Type listType = new TypeToken<List<InfoItem>>() {}.getType();
gson.fromJson(jsonString2, listType);
The Info object is a list because of the []. You have to use the following code to deserialze it:
EDIT:
public class Info {
// as in your question
public String name;
...
}
public class Data {
#SerializedName("Info")
public List<Info> info;
}
Then just use the data class to deserialize your json.

Categories