Looking to parse some Json and parse out array of arrays. Unfortunately I cannot figure out how to handle nested arrays within the json.
json
{
"type": "MultiPolygon",
"coordinates": [
[
[
[
-71.25,
42.33
],
[
-71.25,
42.33
]
]
],
[
[
[
-71.23,
42.33
],
[
-71.23,
42.33
]
]
]
]
}
What I have implemented when I just an a single array.
public class JsonObjectBreakDown {
public String type;
public List<List<String[]>> coordinates = new ArrayList<>();
public void setCoordinates(List<List<String[]>> coordinates) {
this.coordinates = coordinates;
}
}
parsing call
JsonObjectBreakDown p = gson.fromJson(withDup, JsonObjectBreakDown.class);
You've got an array of arrays of arrays of arrays of Strings. You need
public List<List<List<String[]>>> coordinates = new ArrayList<>();
The following
public static void main(String args[]) {
Gson gson = new Gson();
String jsonstr ="{ \"type\": \"MultiPolygon\",\"coordinates\": [ [ [ [ -71.25, 42.33 ], [ -71.25, 42.33 ] ] ], [ [ [ -71.23, 42.33 ], [ -71.23, 42.33 ] ] ] ]}";
JsonObjectBreakDown obj = gson.fromJson(jsonstr, JsonObjectBreakDown.class);
System.out.println(Arrays.toString(obj.coordinates.get(0).get(0).get(0)));
}
public static class JsonObjectBreakDown {
public String type;
public List<List<List<String[]>>> coordinates = new ArrayList<>();
public void setCoordinates(List<List<List<String[]>>> coordinates) {
this.coordinates = coordinates;
}
}
prints
[-71.25, 42.33]
Related
When I call my API with a request body I deserialize it with the variable name in my POJO. I modify the same list and return back but it duplicates the list
#JsonSerialize
#JsonIgnoreProperties(ignoreUnknown = true)
public class UASchema {
#JsonProperty("metric_id")
private ArrayList<String> fMetricId;
#JsonProperty("schema")
private ArrayList<String> fSchema;
#JsonProperty("hash")
private String fHash;
...
...
//getter and setters
}
Request body is
{
"data" : [
{
"metric_id": ["k1", "ak2", "d90"],
"schema": ["s1", "s2"]
},
{
"metric_id": ["k21", "k22"],
"schema": ["a11", "s22"]
}
]
}
Response I get is (added hash)
{
"result": [
{
"fmetricId": [
"k1",
"ak2",
"d90"
],
"fschema": [
"s1",
"s2"
],
"metric_id": [
"k1",
"ak2",
"d90"
],
"schema": [
"s1",
"s2"
],
"hash": "389abc9093442cfd2aee1f20807ba467"
},
{
"fmetricId": [
"k21",
"k22"
],
"fschema": [
"a11",
"s22"
],
"metric_id": [
"k21",
"k22"
],
"schema": [
"a11",
"s22"
],
"hash": "5f366dde65b69fa679f95a81f3115b7f"
}
]
}
It duplicates the list and not correctly serializing it. I want the response to just have the same list as request body and I added hash back.
It looks like your algorithm duplicates entries or you manually generated getters and setters which duplicate output. By default Jackson does not add extra entries. See below example how you can do that, I generated getters and setters in IDE. f-fieldName pattern for fields is outdated and you should use regular names. See, for example, Google's Java Guide:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.util.List;
import java.util.UUID;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
Root root = mapper.readValue(jsonFile, Root.class);
root.getData().forEach(s -> s.setfHash(UUID.randomUUID().toString()));
System.out.println(mapper.writeValueAsString(root));
}
}
class Root {
private List<UASchema> data;
public List<UASchema> getData() {
return data;
}
public void setData(List<UASchema> data) {
this.data = data;
}
#Override
public String toString() {
return "Root{" +
"data=" + data +
'}';
}
}
class UASchema {
#JsonProperty("metric_id")
private List<String> fMetricId;
#JsonProperty("schema")
private List<String> fSchema;
#JsonProperty("hash")
private String fHash;
public List<String> getfMetricId() {
return fMetricId;
}
public void setfMetricId(List<String> fMetricId) {
this.fMetricId = fMetricId;
}
public List<String> getfSchema() {
return fSchema;
}
public void setfSchema(List<String> fSchema) {
this.fSchema = fSchema;
}
public String getfHash() {
return fHash;
}
public void setfHash(String fHash) {
this.fHash = fHash;
}
#Override
public String toString() {
return "UASchema{" +
"fMetricId=" + fMetricId +
", fSchema=" + fSchema +
", fHash='" + fHash + '\'' +
'}';
}
}
Above code prints:
{
"data" : [ {
"metric_id" : [ "k1", "ak2", "d90" ],
"schema" : [ "s1", "s2" ],
"hash" : "80dcf06d-1d83-463c-afb8-edef8efdc71f"
}, {
"metric_id" : [ "k21", "k22" ],
"schema" : [ "a11", "s22" ],
"hash" : "a83d7981-4b80-4318-a632-f3c91d14379b"
} ]
}
What is the quickest way to parse this json array into a list?
[
["FundRequest"],
["nOS"],
["NEX"],
["DREP"],
["ChromaWay"],
["Jura"],
["Origo"],
["Phantasma"],
["NuCypher"],
["Oasis Labs"]
]
Its being generated from the following code:
private void getNames(String spreadsheetUrl) {
JSONObject json = readJsonFromUrl(spreadsheetUrl);
String result = json.get("values").toString();
log.debug("Found: {}", result);
}
The output is from the following json response:
{
"range": "Frontpage!E6:E15",
"majorDimension": "ROWS",
"values": [
[
"FundRequest"
],
[
"nOS"
],
[
"NEX"
],
[
"DREP"
],
[
"ChromaWay"
],
[
"Jura"
],
[
"Origo"
],
[
"Phantasma"
],
[
"NuCypher"
],
[
"Oasis Labs"
]
]
}
You could use a library like GSON:
Install it with maven:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
EDIT:
If you're trying to parse this:
{
"range": "Frontpage!E6:E15",
"majorDimension": "ROWS",
"values": [
[
"FundRequest"
],
[
"nOS"
],...
as a java object then create a wrapper class for your json entity:
public class Wrapper {
private String range;
private String majorDimension;
private List<?> values;
/**
* #return the range
*/
public String getRange() {
return range;
}
/**
* #return the values
*/
public List<?> getValues() {
return values;
}
/**
* #param values the values to set
*/
public void setValues(List<?> values) {
this.values = values;
}
/**
* #return the majorDimension
*/
public String getMajorDimension() {
return majorDimension;
}
/**
* #param majorDimension the majorDimension to set
*/
public void setMajorDimension(String majorDimension) {
this.majorDimension = majorDimension;
}
/**
* #param range the range to set
*/
public void setRange(String range) {
this.range = range;
}
}
Then using GSON you can parse a Json string into a wrapper object:
Gson gson = new GsonBuilder().create();
Wrapper w = gson.fromJson(jsonString, Wrapper.class);
Check this: http://www.javacreed.com/simple-gson-example/
EDIT:
If you're trying to parse this:
[
["FundRequest"],
["nOS"],
["NEX"],
["DREP"],
["ChromaWay"],
["Jura"],
["Origo"],
["Phantasma"],
["NuCypher"],
["Oasis Labs"]
]
As an array of arrays, then using gson you can do:
List<?> arr = gson.fromJson("[[\"FundRequest\"],[\"nOS\"],...]", List.class);
System.out.println(arr);
The println shall print:
[[FundRequest], [nOS], ...]
The json array of arrays shall be parsed as a list of lists
Hope this helps
I have this class:
#Getter
#Setter
IntestatarioPrivacySospensiva {
private IntestatarioInput intestatario;
private List<DatiPrivacySospensiva> datiPrivacy;
private String sportelloRiferimento;
private String riferimento;
private String note;
private String accettazioneConsensoC1;
private String accettazioneConsensoC3;
}
I have to make a JSON request to map this object, I have made this but it is never seen as IntestatarioPrivacySospensiva object.
[
{
//this are intestatarioInput variable
"abi":"abi",
"cf":"cf",
"ndg":"ndg"
},
{//This are datiprivacy variable
"tipoConsenso":"tipoConsenso",
"consenso":"consenso"
},
{
"sportelloRiferimento":"sportelloRif",
"riferimento":"riferimento",
"note":"note",
"accettazioneConsensoC1":"true",
"accettazioneConsensoC3":"false"
}
]
My service have in the request ArrayList x; how i have to map it in json?
I'm using Postman to send JSON.
I believe this should work:
[{
"sportelloRiferimento":"sportelloRif",
"riferimento":"riferimento",
"note":"note",
"accettazioneConsensoC1":"true",
"accettazioneConsensoC3":"false",
"intestatario" : {
"abi":"abi",
"cf":"cf",
"ndg":"ndg"
},
"datiPrivacy" : [ {
"tipoConsenso":"tipoConsenso",
"consenso":"consenso"
} ]
},
{
"sportelloRiferimento":"sportelloRif",
"riferimento":"riferimento",
"note":"note",
"accettazioneConsensoC1":"true",
"accettazioneConsensoC3":"false",
"intestatario" : {
"abi":"abi",
"cf":"cf",
"ndg":"ndg"
},
"datiPrivacy" : [ {
"tipoConsenso":"tipoConsenso",
"consenso":"consenso"
} ]
}]
You can use Jackson 2.x to get JSON strings from your Java objects. Checkout the below example:
https://www.mkyong.com/java/jackson-2-convert-java-object-to-from-json/
I have a List of Objects with multiple fields. Based on the API call, the List would be returned with only a specific set of fields. When I use transient - it does not serialize that particular field. But, that field should be returned for another API call. I am using Gson.
In the example below, based on the API, I wanted to print a list of Table instances with only E.g. "name" of the Table instances, or both "name" and "location", or just location. There could be 30 fields in the Table Object.
One way is to map it to a POJO for each scenario and then print it out. Is there a better way to do this? where you can select/choose/constrain which field gets serialized.
E.g.
package Testing;
import java.util.ArrayList;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class TestJson {
public static Gson obGson = new GsonBuilder().setPrettyPrinting().create();
public static void main(String[] args) {
ArrayList<Table> myTable = new ArrayList<Table>();
myTable.add(new Table("John", "Chicago"));
myTable.add(new Table("David", "Seattle"));
myTable.add(new Table("June", "Dallas"));
System.out.println(obGson.toJson(myTable));
}
}
class Table {
String name;
String location;
public Table (String _name, String _location) {
name = _name;
location = _location;
}
}
The output for the above looks like this. When API-1 is called then the output should like below.
[
{
"name": "John",
"location": "Chicago"
},
{
"name": "David",
"location": "Seattle"
},
{
"name": "June",
"location": "Dallas"
}
]
But when API-2 is called then the output should like below. Only return the fields that are approved for that API call.
[
{
"name": "John"
},
{
"name": "David"
},
{
"name": "June"
}
]
Similarly, the return could be managed based on the API call.
Implement ExclusionStrategy like
#RequiredArgsConstructor
public class FieldExclusionStrategy implements ExclusionStrategy {
#NonNull
private final Collection<String> serializedFields;
#Override
public boolean shouldSkipField(FieldAttributes f) {
if(serializedFields.contains(f.getName())) return false;
return true;
}
#Override
public boolean shouldSkipClass(Class<?> clazz) { return false; }
}
Use like
#Test
public void testShouldSkipField() {
Gson gson;
Table table = new Table();
Collection<String> serializedFields = new ArrayList<>();
ArrayList<Table> myTable = new ArrayList<Table>();
myTable.add(new Table("John", "Chicago"));
myTable.add(new Table("David", "Seattle"));
myTable.add(new Table("June", "Dallas"));
serializedFields.add("name");
gson = new GsonBuilder()
.setPrettyPrinting()
.addSerializationExclusionStrategy(
new FieldExclusionStrategy(serializedFields))
.create();
log.info("\n{}", gson.toJson(myTable));
serializedFields.add("location");
gson = new GsonBuilder()
.setPrettyPrinting()
.addSerializationExclusionStrategy(
new FieldExclusionStrategy(serializedFields))
.create();
log.error("\n{}", gson.toJson(myTable));
serializedFields.remove("name");
gson = new GsonBuilder()
.setPrettyPrinting()
.addSerializationExclusionStrategy(
new FieldExclusionStrategy(serializedFields))
.create();
log.error("\n{}", gson.toJson(myTable));
}
Above would log something like
2017-12-23 19:47:17.028 INFO org.example.gson.FieldExclusionStrategyTest:37 -
[
{
"name": "John"
},
{
"name": "David"
},
{
"name": "June"
}
]
2017-12-23 19:47:17.034 ERROR org.example.gson.FieldExclusionStrategyTest:44 -
[
{
"name": "John",
"location": "Chicago"
},
{
"name": "David",
"location": "Seattle"
},
{
"name": "June",
"location": "Dallas"
}
]
2017-12-23 19:47:17.035 ERROR org.example.gson.FieldExclusionStrategyTest:51 -
[
{
"location": "Chicago"
},
{
"location": "Seattle"
},
{
"location": "Dallas"
}
]
You need to build GSON again after changing list of serialized field names.
GSON caches internally the result - true|false - upon first call for some field name and does not query it again for cached field name.
And to add ExclusionStrategy you need to build GSON with GsonBuilder which then registers ExclusionStrategy (or many of them).
See also my question about this topic.
I got a problem so I'm using the google places api.
I will not write the whole code here because it's too big. But this is what I get for resuls whenever I call the google api:
{
"html_attributions" : [],
"result" : {
"address_components" : [
{
"long_name" : "48",
"short_name" : "48",
"types" : [ "street_number" ]
},
{
"long_name" : "Pirrama Road",
"short_name" : "Pirrama Road",
"types" : [ "route" ]
},
{
"long_name" : "Pyrmont",
"short_name" : "Pyrmont",
"types" : [ "locality", "political" ]
},
{
"long_name" : "NSW",
"short_name" : "NSW",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "AU",
"short_name" : "AU",
"types" : [ "country", "political" ]
},
{
"long_name" : "2009",
"short_name" : "2009",
"types" : [ "postal_code" ]
}
],
"events" : [
{
"event_id" : "9lJ_jK1GfhX",
"start_time" : 1293865200,
"summary" : "<p>A visit from author John Doe, who will read from his latest book.</p>
<p>A limited number of signed copies will be available.</p>",
"url" : "http://www.example.com/john_doe_visit.html"
}
],
"formatted_address" : "48 Pirrama Road, Pyrmont NSW, Australia",
"formatted_phone_number" : "(02) 9374 4000",
"geometry" : {
"location" : {
"lat" : -33.8669710,
"lng" : 151.1958750
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id" : "4f89212bf76dde31f092cfc14d7506555d85b5c7",
"international_phone_number" : "+61 2 9374 4000",
"name" : "Google Sydney",
"rating" : 4.70,
"reference" : "CnRsAAAA98C4wD-VFvzGq-KHVEFhlHuy1TD1W6UYZw7KjuvfVsKMRZkbCVBVDxXFOOCM108n9PuJMJxeAxix3WB6B16c1p2bY1ZQyOrcu1d9247xQhUmPgYjN37JMo5QBsWipTsnoIZA9yAzA-0pnxFM6yAcDhIQbU0z05f3xD3m9NQnhEDjvBoUw-BdcocVpXzKFcnMXUpf-nkyF1w",
"reviews" : [
{
"aspects" : [
{
"rating" : 3,
"type" : "quality"
}
],
"author_name" : "Simon Bengtsson",
"author_url" : "https://plus.google.com/104675092887960962573",
"text" : "Just went inside to have a look at Google. Amazing.",
"time" : 1338440552869
},
{
"aspects" : [
{
"rating" : 3,
"type" : "quality"
}
],
"author_name" : "Felix Rauch Valenti",
"author_url" : "https://plus.google.com/103291556674373289857",
"text" : "Best place to work :-)",
"time" : 1338411244325
},
{
"aspects" : [
{
"rating" : 3,
"type" : "quality"
}
],
"author_name" : "Chris",
"text" : "Great place to work, always lots of free food!",
"time" : 1330467089039
}
],
"types" : [ "establishment" ],
"url" : "http://maps.google.com/maps/place?cid=10281119596374313554",
"vicinity" : "48 Pirrama Road, Pyrmont",
"website" : "http://www.google.com.au/"
},
"status" : "OK"
}
Now I all save that here:
package com.androidhive.googleplacesandmaps;
import java.io.Serializable;
import com.google.api.client.util.Key;
/** Implement this class from "Serializable"
* So that you can pass this class Object to another using Intents
* Otherwise you can't pass to another actitivy
* */
public class Place implements Serializable {
#Key
public String id;
#Key
public String name;
#Key
public String reference;
#Key
public String icon;
#Key
public String vicinity;
#Key
public Geometry geometry;
#Key
public String formatted_address;
#Key
public String formatted_phone_number;
#Override
public String toString() {
return name + " - " + id + " - " + reference;
}
public static class Geometry implements Serializable
{
#Key
public Location location;
}
public static class Location implements Serializable
{
#Key
public double lat;
#Key
public double lng;
}
}
Here is how I get the results:
public class PlacesList implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Key
public String status;
#Key
public List<Place> results;
}
Now my question is:
In the result i get from google you can see the photo_reference. But it's an array and I just need to have the first photo_reference. How can I get that in my code?
JSONObject res = // your google api results
JSONArray photos = res.getJSONArray("photo_reference"); // Extract the JSONArray
// Get the item at index 0, which should be a reference to the first image
String photo = photos.getString(0);
This will get you the reference to the photo, then it looks like you have to make another request to the Photo API.
https://maps.googleapis.com/maps/api/place/photo?parameters
For more information on how to use the Photo API, look at https://developers.google.com/places/documentation/photos