I have a Json like below:
{
"searchResults": {
"searchCriteria": {
"location": {
"originalLocation": null
},
"startAndEndDate": {
"start": "2016-10-06T00:00:00",
"end": "2016-10-09T00:00:00"
},
"solution": [
{
"resultID": "O1MDc1MD",
"selected": false,
"charges": {
"localCurrencyCode": "USD",
"averagePricePerNight": 153
},
"starRating": 3.5
},
{
"resultID": "0MDc1MD",
"selected": false,
"charges": {
"localCurrencyCode": "USD",
"averagePricePerNight": 153
},
"starRating": 3.5
}
....
I have class with attributes starRating and averagePricePerNight which essentially formulates into my POJO.
class ResponseModel {
Int starRating; Int averagePricePerNight
}
I want to parse this JSON and return a List containing :
List(ResponseModel(3.5,900), ResponseModel(3.5,100), ResponseModel(4.5,1000))
I tried to get the json as a List but then i am unable to find examples to get two elements from JSon.
You can write a custom deserializer:
class Deserializers {
public static ResponseModel responseModelDeserializer(JsonElement json, Type typeOfT,
JsonDeserializationContext context) {
JsonObject obj1 = json.getAsJsonObject();
JsonObject obj2 = obj1.get("charges").getAsJsonObject();
double starRating = obj1.get("starRating").getAsDouble();
int averagePricePerNight = obj2.get("averagePricePerNight").getAsInt();
return new ResponseModel(starRating, averagePricePerNight);
}
}
Register it when building Gson:
Gson gson = new GsonBuilder()
.registerTypeAdapter(ResponseModel.class,
(JsonDeserializer<ResponseModel>) Deserializers::responseModelDeserializer
// ^^^ Cast is needed because the parameter has type Object
)
.create();
(Other options include, besides a method reference, are; lambda, anonymous class, or just a regular class. But this one is my favourite.)
Parse your json:
// Get root json object
JsonObject root = new JsonParser().parse(input).getAsJsonObject();
Type tt = new TypeToken<List<ResponseModel>>() {}.getType();
// Get array
List<ResponseModel> mo = gson.fromJson(root.get("solution"), tt);
System.out.println(mo); // [3.5 : 153, 3.5 : 153]
Where ResponseModel is:
class ResponseModel {
private final double starRating;
private final int averagePricePerNight;
public ResponseModel(double starRating, int averagePricePerNight) {
this.starRating = starRating;
this.averagePricePerNight = averagePricePerNight;
}
#Override
public String toString() {
return String.format("%s : %s", starRating, averagePricePerNight);
}
}
I made starRating a double since it seems to be one in your example.
Related
My Rest API is returning the following response, in which only the inner list is required, all data shall be discarded:
{
"meta": [],
"links": [],
"body": [
{
"meta": [],
"links": [],
"body": {
"field1": "value1",
"fieldn": "valuen"
} // <-----
},
{
"meta": [],
"links": [],
"body": {
"field1": "value1",
"fieldn": "valuen"
} // <-----
}
]
}
Is there any way in Gson or another other java library to fetch an array of the body or a straightforward way of doing that? Or maybe even using standard of java 8?
Or, should I use a standard iterator as follows:
//Old way to do this
JSONArray BodyArr = (JSONArray) jsonObject.get("Body");
Iterator<JSONObject> itBody = BodyArr.iterator();
int teller = 0;
while (itBody.hasNext()) {
JSONObject bodyObj = itBody.next();
JSONObject body = (JSONObject) bodyObj.get("Body");
}
Also in mysql we have way to do that using notation ($.body.body[] etc.). Is there any notational way to fetch the object
I think we have a nicely written article on this.
Json object iteration
If you have a class that represents an object in the array, then you can deserialize the JSONArray to an array of that class using public <T> T fromJson(JsonElement json, java.lang.Class<T> classOfT) throws JsonSyntaxException on the Gson class:
class BodyItem {
public String[] meta;
public String[] links;
public String field1;
public String fieldn;
}
public BodyItem[] getBodyItems(final Gson gson, final JsonObject jsonObject) {
final JsonElement body = jsonObject.get("body");
return gson.fromJson(body, BodyItem[].class);
}
public static void main(final String[] args) {
final String response = "<your REST API JSON response>";
final Gson gson = new Gson();
final JsonObject jsonObject = gson.fromJson(response, JsonObject.class);
final BodyItem[] bodyItems = getBodyItems(gson, jsonObject);
}
If you want a more notational way of accessing fields in Gson objects, you can use JsonObject's convenience accessors:
JsonArray getAsJsonArray(java.lang.String memberName)
JsonObject getAsJsonObject(java.lang.String memberName)
JsonPrimitive getAsJsonPrimitive(java.lang.String memberName)
And then with a JsonArray, you can iterate with for (final JsonElement element : jsonArray) or .forEach, and you can get JsonElements with the JsonElement get(int i) accessor.
So, say you had your original JsonObject response and wanted to get the value of body.field1 in the second element of the body list, you might do:
String value = jsonObject
.getAsJsonArray("body")
.get(1)
.getAsJsonObject()
.getAsJsonObject("body")
.getAsJsonObject("field1");
My API needs to return a list of entry objects from the JSON below. I am using jersey and jackson. I would ideally like to only create a java class PermissionEnty , and my API to return a list of PermissionEntry objects from the JSON. I am not able to deserialize using the below approach? Can someone advise what could be the issue? I have added UNWRAP_ROOT_VALUE so I presume the 'list' node it ignored, and I would get items below 'list' node.
public class PermissionEntry {
private String id;
private String displayName;
private String memberType;
}
and the json;
{
"list": {
"pagination": {
"count": 5,
"hasMoreItems": false,
},
"entries": [
{
"entry": {
"displayName": "norma",
"id": "norma",
"memberType": "PERSON"
}
},
{
"entry": {
"displayName": "clara",
"id": "clara",
"memberType": "PERSON"
}
},
{
"entry": {
"displayName": "michael",
"id": "mich",
"memberType": "PERSON"
}
}
]
}
}
PermissionEntries
public class PermissionEntries {
#JsonProperty(value = "entries")
#JsonDeserialize(using = PermissionEntryDeserializer.class)
private List<PermissionEntry> entries;
public List<PermissionEntry> getEntries() {
return entries;
}
public void setEntries(List<PermissionEntry> entries) {
this.entries = entries;
}
}
Below is the deserializer that I am using
public class PermissionEntryDeserializer extends JsonDeserializer<List<PermissionEntry>> {
private static final String ENTRY = "entries";
private static final ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
private static final CollectionType collectionType =
TypeFactory
.defaultInstance()
.constructCollectionType(List.class, PermissionEntry.class);
#Override
public List<PermissionEntry> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
ObjectNode objectNode = mapper.readTree(jsonParser);
JsonNode nodeEntries = objectNode.get(ENTRY);
if (null == nodeEntries // if no ENTRY node could be found
|| !nodeEntries.isArray() // or ENTRY node is not an array
|| !nodeEntries.elements().hasNext()) // or ENTRY node doesn't contain any entry
return null;
return mapper.readerFor(collectionType).readValue(nodeEntries);
}
}
Service API
public Optional<List<PermissionEntry>> getPermissionsForGroup(String groupName) {
Response response = getTarget()
.path("/api/group/" + groupName + "/members")
.request()
.get();
PermissionEntries list = response.readEntity(PermissionEntries.class);
}
I don't understand what you mean in this question 'Can someone please tell me how many java classes do I need to create to get a list of entries.' but you had already an entry object called PermissionEntry. You will have the list of this object.
This is the jersey client of your data with jakcson .
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
String URL = "http://{{host}}:{{port}}/entry";
WebResource webResourceGet = client.resource(URL);
ClientResponse response = webResourceGet.accept("application/json").get(ClientResponse.class);
String output = response.getEntity(String.class);
ResponseList responseList= mapper.readValue(output , ResponseList .class);//here is the permissionEntry list that you wil have
Also, you should create an object given name as Pagination for pagination that is in the json data. You can make an another object that includes List<PermissionEntry> and Pagination called ResponseList.
I need to create json of this format:
{
"array": [
1482922777223,
0.014221191,
0.014221191,
0.014221191
]
}
Data.class
public class Data {
#SerializedName("array")
#Expose
private List<Float> array = null;
}
to convert object to JSON string i use gson library.
List<Float> list = new ArrayList<>();
list.add((float)1482922777223);
list.add(0.014221191);
list.add(0.014221191);
list.add(0.014221191);
Data data = new Data(list);
Gson gson = new Gson();
String json = gson.toJson(data);
Result string:
{
"array": [
1.4829219E12, <--- HOW TO GET HERE 1482922777223?
0.014221191,
0.014221191,
0.014221191
]
}
Please help!
You need to register TypeAdapter for Float values.
E.g:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Float.class, new JsonSerializer<Float>() {
#Override
public JsonElement serialize(final Float src, final Type typeOfSrc, final JsonSerializationContext context) {
BigDecimal value = BigDecimal.valueOf(src);
return new JsonPrimitive(value);
}
});
Gson gson = gsonBuilder.create();
String json = gson.toJson(data);
Output :
{
"array": [
1482922777223,
0.014221191,
0.014221191,
0.014221191
]
}
I have written a program that does some probability calculations and gives its results in the form of arrays. I want to convert these results to JSON format, but I am having issues.
I want my json object to look like this:
{
"totalSuggestions": 6,
"routes": {
"rank_2": {
"Source": "ABC",
"Weight": "0.719010390625",
"Destination": "XYZ"
},
"rank_1": {
"Source": "XYZ",
"Weight": "0.7411458281249999",
"Destination": "ABC"
},
"rank_0": {
"Source": "LMN",
"Weight": "0.994583325",
"Destination": "PQR"
}
}
}
What I understood is that I need to have an object class with the structure of my objects. For now I am experimenting with the rank object only but failing to form the required JSON.
My code for the object structure:
public class Object {
int rank_;
public class Inner{
String Source;
String Destination;
String Weightage;
}
}
I can pass either an instance of Object or an instance of Inner to toJson() method so I either get {"rank_":1} or {"Source":"ABC","Destination":"XYZ","Weightage":"123"}.
I cant seem to put each of the inner object to the corresponding rank object.
I did it with relative ease with org.json but that library has some issues with Android studio so I had to switch to Gson. What I did earlier (which worked as well) was:
public JSONObject convertToJson(int mkr, String[][] result){
JSONObject outerObj = new JSONObject();
JSONObject innerObj = new JSONObject();
JSONObject[] temp = new JSONObject[mkr];
outerObj.put("totalSuggestions", marker);
outerObj.put("routes",innerObj);
for (int i=0;i<marker;i++){
String[] useless = result[i][0].split("-");
temp[i]= new JSONObject();
temp[i].put("Source",useless[0] );
temp[i].put("Destination", useless[1]);
temp[i].put("Weight", result[i][1]);
innerObj.put("rank_"+i, temp[i]);
}
System.out.println(outerObj.toString());
return outerObj;
}
Well, first: related objects should probably be in a class together. So lets start with a simple class:
public class Results {
int mkr;
String[][] result;
}
Now we want to serialize it. We could construct a different data structure, or we could just write our own custom serializer. We want to have our custom class to allow us to use Gson's type inference for doing so, plus the code is just easier to understand. I will show you how to serialize the data structure, and I'll leave the deserialization as an exercise for you.
We create a TypeAdapter<Results>:
public class ResultsAdapter extends TypeAdapter<Results> {
public Results read(JsonReader reader) throws IOException {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return null;
}
// exercise for you
return results;
}
public void write(JsonWriter writer, Results value) throws IOException {
if (value == null) {
writer.nullValue();
return;
}
writer.beginObject();
writer.name("totalSuggestions").value(value.mkr);
writer.name("routes");
writer.beginObject();
for(int i = 0; i < value.mkr; i++) {
writer.name("rank_"+i);
writer.beginObject();
String[] sourceDestSplit = result[i][0].split("-");
writer.name("Source").value(sourceDestSplit[0]);
writer.name("Destination").value(sourceDestSplit[1]);
writer.name("Weight").value(result[i][1]);
writer.endObject();
}
writer.endObject();
writer.endObject();
}
}
You can then call this method by doing (note: should only create the Gson object once, but I did it this way to keep the code short):
public String convertToJson(Results results) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(new ResultsAdapter()):
Gson gson = builder.build();
return gson.toJson(results);
}
This will work you the way you've asked, but I strongly recommend using JSON's array syntax instead (using []). Try this instead:
public void write(JsonWriter writer, Results value) throws IOException {
if (value == null) {
writer.nullValue();
return;
}
writer.beginObject();
writer.name("totalSuggestions").value(value.mkr);
writer.name("routes");
writer.beginArray();
for(int i = 0; i < value.mkr; i++) {
writer.beginObject();
String[] sourceDestSplit = result[i][0].split("-");
writer.name("Source").value(sourceDestSplit[0]);
writer.name("Destination").value(sourceDestSplit[1]);
writer.name("Weight").value(result[i][1]);
writer.endObject();
}
writer.endArray();
writer.endObject();
}
Doing it this will will result in JSON that looks like this, which will be easier to deserialize on the other side and iterate through, because you won't have to dynamically generate maps for the keys.:
{
"totalSuggestions": 6,
"routes": [
{
"Source": "ABC",
"Weight": "0.719010390625",
"Destination": "XYZ"
},
{
"Source": "XYZ",
"Weight": "0.7411458281249999",
"Destination": "ABC"
},
{
"Source": "LMN",
"Weight": "0.994583325",
"Destination": "PQR"
}
]
}
I landed here while searching for a similar solution for the com.google.gson.JsonObject library. Now, I've found it:
JsonObject mainJson = new JsonObject();
JsonObject innerJson = new JsonObject();
innerJson.addProperty("#iot.id", "31");
mainJson.add("Datastream", innerJson); // <-- here the nesting happens
mainJson.addProperty("result", 12.3);
// fetch inner variable like this
System.out.println(mainJson.get("Datastream").getAsJsonObject().get("#iot.id").getAsString());
This works fine for me using the com.google.gson.JsonObject library.
For the record, this is what i did.
import java.util.*;
public class DataObject {
public int Suggestions;
HashMap<String, route> routes = new HashMap<>();
//constructor
public DataObject(int mkr, String[][] routesArr){
Suggestions = mkr;
{
for (int i=0;i<Suggestions;i++){
routes.put("rank_"+(i+1),new route(routesArr[i]));
}
}
}
//class to populate the hashmap
public class route{
public String Origin;
public String Destination;
public String Weight;
public route(String arr[]){
String[] splitter = arr[0].split("-");
this.Origin = splitter[0];
this.Destination = splitter[1];
this.Weight = arr[1];
}
}
}
I want to make a post request with volley to a REST API.
Therefore, I create a JSONObject and put a JSON String generated from a class in it.
JSONObject jsonObject = new JSONObject();
String json = gson.toJson(MyClazz);
try {
jsonObject.put(PARAM, json);
}
catch (JSONException e1) {
e1.printStackTrace();
}
The problem is that the correct calculated JSON String gets escaped and can't be recognized on the back end.
So toJson() gives something like:
{
"device_identifier":"324234234",
"name":"NameMe",
"list":[
{"prop":"A","prop2":-10},
{"prop":"B","prop2":-12}
]
}
The jsonObject's output is like
{
"PARAM":{
\"device_identifier\":\"324234234\",
\"name\":\"NameMe\",
\"list\":[
{\"prop\":\"A\",\"prop2\":-10},
{\"prop\":\"B\","\prop2\":-12}
]
}
}
I need the PARAM for the JSON structure so I can't give it directly to the REST-API. Any ideas how I can avoid the additional escaping?
You could wrap your MyClazz object with a simple wrapper object, and then pass that wrapped object to Gson's toJson method.
Given this class based on your example JSON,
public class MyClazz {
public String device_identifier;
public String name;
public List<Prop> list;
public class Prop {
public String prop;
public Integer prop2;
}
}
here's a possible wrapper implementation. Note the use of com.google.gson.annotations.SerializedName which tells Gson to use the PARAM key in the JSON representation.
public class MyClazzWrapper {
public MyClazzWrapper(MyClazz myClazz) {
this.myClazz = myClazz;
}
#SerializedName("PARAM")
private MyClazz myClazz;
}
And here's an example using it:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
MyClazz myClazz = gson.fromJson("{\"device_identifier\":\"324234234\",\"name\":\"NameMe\",\"list\":[{\"prop\":\"A\",\"prop2\":-10},{\"prop\":\"B\",\"prop2\":-12}]}", MyClazz.class);
MyClazzWrapper wrapped = new MyClazzWrapper(myClazz);
System.out.println(gson.toJson(wrapped));
The above will print:
{
"PARAM": {
"device_identifier": "324234234",
"name": "NameMe",
"list": [
{
"prop": "A",
"prop2": -10
},
{
"prop": "B",
"prop2": -12
}
]
}
}