Json multiple string arrays into multiple Java String list - java

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.

Related

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

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)

Parsing JSON from WebResource to a usable Java Object

i try to use some web api, so i do this
public static void main(String[] args) {
// Create Jersey client
Client client = Client.create();
// GET request to findBook resource with a query parameter
String getSoccersSeasonsUrl = "http://api.football-data.org/v1/soccerseasons";
WebResource webResourceGet = client.resource(getSoccersSeasonsUrl);
webResourceGet.header("X-Auth-Token", myToken);
ClientResponse response = webResourceGet.get(ClientResponse.class);
String output = response.getEntity(String.class);
System.out.println(output);
}
output
[{"_links":{"self":{"href":"http://api.football-data.org/v1/soccerseasons/394"},"teams":{"href":"http://api.football-data.org/v1/soccerseasons/394/teams"},"fixtures":{"href":"http://api.football-data.org/v1/soccerseasons/394/fixtures"},
"leagueTable":{"href":"http://api.football-data.org/v1/soccerseasons/394/leagueTable"}},
"id":394,
"caption":"1. Bundesliga 2015/16",
"league":"BL1",
"year":"2015",
"currentMatchday":24,
"numberOfMatchdays":34,
"numberOfTeams":18,
"numberOfGames":306,
"lastUpdated":"2016-03-01T20:50:44Z ยป}
how can i fill from this output directly in a java ArrayList of object like:
public class SoccerSeason {
public SoccerSeason() {
}
private long id;
private String caption;
private String league;
private String year;
private long currentMatchday;
private long numberOfMatchdays;
private long numberOfTeams;
private long numberOfGames;
private String lastUpdated;
}
when i try to get directly SoccerSeason output = response.getEntity(SoccerSeason.class); i have a classic com.sun.jersey.api.client.ClientHandlerException
what's missing in my code please? do you have any idea how to do this simply?
What you want is Google's GSON. It can be found with a quick google search, and it has a ton of easy to read documentation.
Add GSON to your projects dependencies/source code, add getters and setters for all of your class members to the class you've created and it should work beautifully.
It is used like this:
Gson gson = new Gson();
SoccerSeason newSoccerSeason = gson.fromJson(webApiResponse, SoccerSeason.class);
String lastUpdated = newSoccerSeason.getLastUpdated();
Where webApiResponse is a String representation of the JSON received as your web API's response. You can also define a class SoccerSeasonList which looks like this:
public class SoccerSeasonList {
ArrayList<SoccerSeason> seasonList;
// getters/setters
}
Of course, your incoming JSON would have to have an object called seasonList containing all of your SoccerSeason objects to match up with this definition.
But then, you could grab your list like so:
SoccerSeasonList seasonList = gson.fromJson(webApiResponse, SoccerSeasonList.class);
ArrayList<SoccerSeason> seasonArr = seasonList.getSeasonList();
And perform operations like so:
for(SoccerSeason ss : seasonArr)
System.out.println(ss.getNumberOfMatchdays());
To recap: You simply match up your JSON object names and literals to their equivalent java types in a class, and call fromJSON on a String containing the JSON received from your web API that you'd like to parse, passing in the class you want the object parsed to.

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.

conversion of array list to json object string

I have a model class method which returns a list of objects which contains all the registered user details. I want to fetch the list resturned by all() method and convert the data into JSON object and pass it to the view like a string. How can I do this conversion of this array list to JSON object?
I was unable to do this by below:
ObjectMapper mapper = new ObjectMapper();
JSONObject json = new JSONObject();
JsonNodeFactory jsonnode = JsonNodeFactory.instance;
ObjectNode result = new ObjectNode(jsonnode);
for (int i = 0; i < list.size(); i++) {
json.put(list.get(i).fname, list.get(i));
System.out.println(json.get("fname"));
}
#Entity
class Mydata extends Model {
#Id
public Long Id;
public String fname;
public String lname;
public String city;
public String state;
/****************** READ/select OPERATION *****************/
public static Finder < Long, Mydata > finder = new Finder(Long.class, Mydata.class);
public static List < Mydata > all() {
return finder.all();
}
public static void createuser(Mydata user) {
user.save();
}
}
To convert ArrayList to Json, just download Open Source json utility from:
http://json.org/java/ or Jar file from here
And just do:
JSONArray jsonAraay = new JSONArray(your_array_list);
That's it
Note: You should have setter/getter in your POJO/MODEL class to convert arraylist to json
Don't bother with org.json, use Jackson all the way:
// list is a List<MyData>
final ObjectMapper mapper = new ObjectMapper();
final Map<String, MyData> map = new HashMap<>();
for (final MyData data: list)
map.put(data.fname, data);
final JsonNode json = mapper.valueToTree(map);
You could use all sorts of third party libraries like others here have suggested, or just use Play's own simplified methods for this (found in play.libs.Json) which works with Jackson objects, but it is integrated into the framework and requires a lot less code to use, for example:
JsonNode myJsonNode = Json.toJson(MyListObject); which converts the List to a JsonNode object, then use something like String jsonResult = Json.stringify(myJsonNode); to convert it into a string representation.
If you are using the JSON in a template, don't forget to wrap it in something like #Html(myJsonString) so it will not escape anything. Otherwise, if you are just outputting the pure JSON to the browser, a simple return ok(jsonResult); will work as Play will automatically set the content type.
Reference link: http://www.playframework.com/documentation/api/2.0/java/play/libs/Json.html
have you looked at this:
http://www.json.org/javadoc/org/json/JSONObject.html#valueToString(java.lang.Object)
JSONObject.valueToString(<<your list of custom object>> OR <<objects>> OR <<map>>)
works just fine...there are some other methods on that lib, if you are interested....

json deserialization problem

Have an array, when the size is 1, the json data I received does NOT contains []; like
{"firstname":"tom"}
when the size is larger than 1, the data I received contains [], like
[{"firstname":"tom"},{"firstname":"robert"}]
Currently my class contains an array property
String[] firstname;
//getter setter omit here
Code to handle this likes
ObjectMapper mapper = new ObjectMapper();
MyClass object = mapper.readValue(json, MyClass.class);
When the size is larger than 1, the deserialization works. However when size is 1, the deserialization failed.
I am currently using jackson, any solution for this problem?
I am wondering if jackson/gson or any other library can handle this?
For Jackson specifically, your best bet would to first bind to a JsonNode or Object, like:
Object raw = objectMapper.readValue(json, Object.class); // becomes Map, List, String etc
and then check what you got, bind again:
MyClass[] result;
if (raw instanceof List<?>) { // array
result = objectMapper.convertValue(raw, MyClass[].class);
} else { // single object
result = objectMapper.convertValue(raw, MyClass.class);
}
But I think JSON you are getting is bad -- why would you return an object, or array, intead of just array of size 1? -- so if at all possible, I'd rather fix JSON first. But if that is not possible, this would work.
Here's how to do it with GSON. Let's assume this object structure:
public class Group{
public Group(final List<Person> members){
this.members = members;
}
private final List<Person> members;
}
public class Person{
public Person(final String firstName, final String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
private final String firstName;
private final String lastName;
}
Here's a deserializer that understands single Person entries as well as arrays of them:
public class GroupDeserializer implements JsonDeserializer<Group>{
#Override
public Group deserialize(final JsonElement json,
final Type typeOfT,
final JsonDeserializationContext context) throws JsonParseException{
List<Person> members;
if(json.isJsonArray()){
final JsonArray array = json.getAsJsonArray();
members = new ArrayList<Person>(array.size());
for(final JsonElement personElement : array){
members.add(getSinglePerson(personElement, context));
}
} else{
members =
Collections.singletonList(getSinglePerson(json, context));
}
return new Group(members);
}
private Person getSinglePerson(final JsonElement element,
final JsonDeserializationContext context){
final JsonObject personObject = element.getAsJsonObject();
final String firstName =
personObject.getAsJsonPrimitive("firstname").getAsString();
final String lastName =
personObject.getAsJsonPrimitive("lastname").getAsString();
return new Person(firstName, lastName);
}
}
And here you can find the necessary Configuration to use this
edit: I guess you would then just extract a JsonElement and check it's isJsonArray() and/or isJsonObject(). Then, just call getAsJsonArray() or getAsJsonObject().
Old answer: Why not just try to extract the array and catch the JsonParseException if it fails. In the catch block, try to extract an object instead.
I know it's not pretty but it should work.
I have faced the same issue when I am trying to deserialize the JSON object which was constructed from XML. (XML-JSON). After quite a bit of research, found that we have a simple fix.
Just set the feature : ACCEPT_SINGLE_VALUE_AS_ARRAY.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
For more info : http://fasterxml.github.com/jackson-databind/javadoc/2.0.0/com/fasterxml/jackson/databind/DeserializationFeature.html#ACCEPT_SINGLE_VALUE_AS_ARRAY
In the first instance it looks like an object, in the second instance it looks like an array of objects (which it sounds like you are expecting).
JSON encoding libraries typically have a "force array" option for cases like this. Failing that, on your client you could check the JSON response and if it's not an array, push the returned objected into an new array.

Categories