Unable to build this Complex JSON Structure - java

I have a inter-related Maps representing the below data .
{
"Soft Drinks": {
"Tin": [
{
"Lean Apple": [
{
"name": "1 Litre"
},
{
"name": "2 Litre"
}
]
},
{
"Clear": [
{
"name": "7 Litre"
},
{
"name": "10 Litre"
}
]
}
],
"Bottled": [
]
}
}
This is my code representing above json data in form of Java code
package test;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
public class Post {
public static void main(String args[]) throws JSONException
{
LinkedList<String> forTinItemsList = new LinkedList<String>();
LinkedList<String> forBottleItemsList = new LinkedList<String>();
JSONObject jsonobj = new JSONObject();
Map<String,LinkedList<String>> categoryitemsMap = new LinkedHashMap<String,LinkedList<String>>();
forTinItemsList.add("Lean Apple");
forTinItemsList.add("Clear");
forBottleItemsList.add("Lemon");
forBottleItemsList.add("Clear");
categoryitemsMap.put("Tin", forTinItemsList);
categoryitemsMap.put("Bottled", forBottleItemsList);
// completion of Categories.
Map<String,LinkedList<String>> subcategory = new LinkedHashMap<String,LinkedList<String>>();
LinkedList<String> forLemonItems = new LinkedList<String>();
forLemonItems.add("1 Litre");
forLemonItems.add("2 Litre");
subcategory.put("Lemon", forLemonItems);
LinkedList<String> forClearItems = new LinkedList<String>();
forClearItems.add("7 Litre");
forClearItems.add("10 Litre");
subcategory.put("Clear", forClearItems);
for (Map.Entry<String, LinkedList<String>> entry : categoryitemsMap.entrySet())
{
String key = entry.getKey();
LinkedList<String> list = entry.getValue();
for(String value : list)
{
System.out.println(key+"\t"+value);
}
//jsonobj.put(entry, arg1);
}
}
}
Could anybody please tell me how can i build the above JSON Structure ??
I was trying with different things m, but i was unsuccessful , the problem i was facing is that i am getting the Bottled Array is also filling up with the same Tin Array items .

To give you an idea of the unholy abomination things would become if you did it this way: here's the data structure that you would have to create to capture the JSON you propose.
Map<String, Map<String, List<Map<String, List<Map<String, String>>>>>> items;
So, feel free to implement this, but if it was me, I would build a data model and then map it with Jackson.

there are libraries that do this for you GSON and Jackson

Related

MongoDB query using aggregation

I need a mongo DB query as well as corresponding java code for the query using aggregation framework for the below mentioned scenario,
Scenario is :
I need to search an array for "seqNo": 4 based on "aC","aI","aN","aT","bID","pD" from collection A.
Please find the collection mentioned below,
Collection A:
/*1*/
{
"_id" : ObjectId("6398b904aa0c28d6193bb853"),
"aC" : "AB",
"aI" : "ABCD",
"aN" : "040000000002",
"aT" : "CA",
"bID" : NumberLong(0),
"pD" : "2019-04-19",
"timeToLive" : ISODate("2019-04-19T00:00:00.000Z"),
"transactions" : [
{
"amt" : NumberDecimal("-12.340"),
"seqNo" : 2,
"valDt" : "2022-10-04"
},
{
"amt" : NumberDecimal("-6.800"),
"seqNo" : 5,
"valDt" : "2022-10-04"
}
]
}
/*2*/
{
"_id" : ObjectId("5d42daa7decf182710080d46"),
"aC" : "AB",
"aI" : "ABCD",
"aN" : "040000000002",
"aT" : "CA",
"bID" : NumberLong(1),
"pD" : "2019-04-19",
"timeToLive" : ISODate("2019-04-19T00:00:00.000Z"),
"transactions" : [
{
"seqNo" : 4,
"amt" : NumberDecimal("26074.000"),
"valDt" : "2019-04-19"
},
{
"seqNo" : 3,
"amt" : NumberDecimal("26074.000"),
"valDt" : "2019-04-19"
}
]
}
Please help me with the query it will be really helpful if explained in detail.
Thanks in advance.
To kick off the answer we will start with the mongo CLI (javascript) because it outlines what we are going to do later in Java.
db.foo.aggregate([
{$match: {"aC": val_aC, "aI": val_aI}},
{$project: {transaction: {$arrayElemAt: [ {$filter: {
input: "$transactions",
cond: {$eq:["$$this.seqNo",4]}
}}, 0] }
}},
{$match: {transaction: {$exists: true}}}
]);
Java is always a little more verbose than python or javascript but here is how I do it. Because my editor matches braces and brackets, I find it easier to construct the query as JSON and then convert it into the required pipeline of Document objects.
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.AggregateIterable;
import org.bson.*;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.HashMap;
import java.math.BigDecimal;
public class agg4 {
private MongoClient mongoClient;
private MongoDatabase db;
private MongoCollection<Document> coll;
private static class StageHelper {
private StringBuilder txt;
public StageHelper() {
this.txt = new StringBuilder();
}
public void add(String expr, Object ... subs) {
expr.replace("'", "\""); // This is the helpful part.
if(subs.length > 0) {
expr = String.format(expr, subs); // this too
}
txt.append(expr);
}
public Document fetch() {
return Document.parse(txt.toString());
}
}
private List<Document> makePipeline() {
List<Document> pipeline = new ArrayList<Document>();
StageHelper s = new StageHelper();
// It is left as an exercise to add all the other individual fields
// that need to be matched and properly pass them in, etc.
String val_aC = "AB";
String val_aI = "ABCD";
s.add(" {'$match': {'aC':'%s','aI':'%s'}}", val_aC, val_aI );
pipeline.add(s.fetch());
s = new StageHelper();
// This is the meat. Find seqNo = 4. Since I suspect seqNo is
// unique, it does no extra good to filter the array to just an array
// array of one; changing the array of 1 (if found of course) to a
// *single* object has more utility, hence use of $arrayElemAt:
s.add(" {'$project': {'transaction': {'$arrayElemAt': [ ");
s.add(" {'$filter': {'input': '$transactions', ");
s.add(" 'cond': {'$eq':['$$this.seqNo', 4]} ");
s.add(" }}, 0]} ");
s.add(" }}");
pipeline.add(s.fetch());
s = new StageHelper();
// If seqNo = 4 could not be found, transaction will be unset so
// use the following to exclude that doc.
s.add(" {'$match': {'transaction': {'$exists': true}}} ");
pipeline.add(s.fetch());
return pipeline;
}
private void doAgg() {
try {
List<Document> pipeline = makePipeline();
AggregateIterable<Document> output = coll.aggregate(pipeline);
MongoCursor<Document> iterator = output.iterator();
while (iterator.hasNext()) {
Document doc = iterator.next();
}
} catch(Exception e) {
System.out.println("some fail: " + e);
}
}
public static void main(String[] args) {
(new agg4()).go(args);
}
public void go(String[] args) {
try {
Map params = new HashMap();
String host = "mongodb://localhost:37017/?replicaSet=rs0";
String dbname = "testX";
String collname = "foo";
mongoClient = MongoClients.create(host);
db = mongoClient.getDatabase(dbname);
coll = db.getCollection(collname, Document.class);
doAgg();
} catch(Exception e) {
System.out.println("epic fail: " + e);
e.printStackTrace();
}
}
If you are using Java 13 or higher, text blocks for String make it even easier:
String s = """
{'$project': {'transaction': {'$arrayElemAt': [
{'$filter': {'input': '$transactions',
'cond': {'$eq':['$$this.seqNo', 4]}
}}, 0]}
}}
""";
pipeline.add(s.fetch());

JSON validation returns different results

I have created a minimal application in order to debug the following problem:
The application is creating a Java object which includes a GeoJsonPoint. When the object gets validated against an automatically created json schema, I receive different results when starting the application multiple times. For example, I am starting the application for 5 times and the result is "Json not valid!". When I start the application another time, I receive the result "Json successfully validated".
The error message when the json is not valid tells me:
/geoPosition/coordinates: instance type (array) does not match any allowed primitive type (allowed: [object])
The following line is randomly returning a different json schema:
JsonNode fstabSchema = schemaFactory.createSchema(inputObj.getClass());
I do not understand that this happens randomly. Has someone seen this behavior before?
To exclude dependency problems during runtime, I have created a jar with all dependencies (jar-with-dependencies)
Below are my files:
pom.xml dependencies:
<dependencies>
<dependency>
<groupId>com.github.reinert</groupId>
<artifactId>jjschema</artifactId>
<version>1.16</version>
</dependency>
<dependency>
<groupId>com.github.java-json-tools</groupId>
<artifactId>json-schema-validator</artifactId>
<version>2.2.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.2.2</version>
</dependency>
</dependencies>
App.java:
package de.s2.json.test;
import java.util.ArrayList;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
public class App
{
public static void main( String[] args )
{
Address address = new Address();
address.setCountry("Deutschland");
GeoJsonPoint geoPoint = new GeoJsonPoint(12, 23);
address.setGeoPosition(geoPoint);
ArrayList<String> ret = null;
try {
ret = Toolbox.validateJson(address);
} catch (ProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(ret != null) {
System.out.println("Json not valid!");
for (int i = 0; i < ret.size(); i++) {
System.out.println(ret.get(i));
}
} else {
System.out.println("Json successfully validated");
}
}
}
Toolbox.java:
package de.s2.json.test;
import java.util.ArrayList;
import java.util.Iterator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.reinert.jjschema.v1.JsonSchemaV4Factory;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.report.ProcessingMessage;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
public class Toolbox {
public static <T> ArrayList<String> validateJson(T inputObj) throws ProcessingException {
com.github.reinert.jjschema.v1.JsonSchemaFactory schemaFactory = new JsonSchemaV4Factory();
schemaFactory.setAutoPutDollarSchema(true);
JsonNode fstabSchema = schemaFactory.createSchema(inputObj.getClass()); // <= here I get different results
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
final JsonSchema schema = factory.getJsonSchema(fstabSchema);
ObjectMapper objectMapper = new ObjectMapper();
JsonNode baseReceiptJson = objectMapper.convertValue(inputObj, JsonNode.class);
ProcessingReport report;
report = schema.validate(baseReceiptJson);
ArrayList<String> validationErrorDetails = new ArrayList<String>();
if (!report.isSuccess()) {
StringBuilder builder = new StringBuilder();
builder.append("Not all required fields are filled with data");
builder.append(System.getProperty("line.separator"));
for (Iterator<ProcessingMessage> i = report.iterator(); i.hasNext();) {
ProcessingMessage msg = i.next();
builder.append(msg.asJson().findValue("instance").findValue("pointer").toString());
builder.append(": ");
builder.append(msg.getMessage());
String detail = msg.asJson().findValue("instance").findValue("pointer").toString() + ": " + msg.getMessage();
detail = detail.replace("\"", "");
validationErrorDetails.add(detail);
builder.append("\n");
}
return validationErrorDetails;
}
return null;
}
}
Address.java:
package de.s2.json.test;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.reinert.jjschema.Attributes;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Address
{
#JsonProperty("country")
private String country = "";
#JsonProperty("geoPosition")
#Attributes(required=false, description="longitude and latitude (it is initialized with 0,0)")
private GeoJsonPoint geoPosition = new GeoJsonPoint(0, 0);
}
Thank you very much for your support!
Update 1:
Answer to Hiran Chaudhuri
If the validation fails, then the schema looks like this:
{
"type": "object",
"properties": {
"country": {
"type": "string"
},
"geoPosition": {
"type": "object",
"properties": {
"coordinates": {
"type": "object"
},
"TYPE": {
"type": "string"
},
"x": {
"type": "number"
},
"y": {
"type": "number"
}
},
"description": "longitude and latitude (it is initialized with 0,0 which is inside the ocean)"
}
},
"$schema": "http://json-schema.org/draft-04/schema#"
}
If it is successful, then it looks like this:
{
"type": "object",
"properties": {
"country": {
"type": "string"
},
"geoPosition": {
"type": "object",
"properties": {
"coordinates": {
"type": "array",
"items": {
"type": "number"
}
},
"TYPE": {
"type": "string"
},
"x": {
"type": "number"
},
"y": {
"type": "number"
}
},
"description": "longitude and latitude (it is initialized with 0,0 which is inside the ocean)"
}
},
"$schema": "http://json-schema.org/draft-04/schema#"
}
As already in the error message indicated, one time the coordinates are an 'object' the other time an 'array'
Update 2
As this issue is blocking me to continue with my project, I have added an "ugly hack" to check in the schema if it contains a GeoJsonPoint. If it is included, it will patch it with the correct values.
package de.s2.json.test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.reinert.jjschema.v1.JsonSchemaV4Factory;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.report.ProcessingMessage;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
public class Toolbox {
public static <T> ArrayList<String> validateJson(T inputObj) throws ProcessingException {
com.github.reinert.jjschema.v1.JsonSchemaFactory schemaFactory = new JsonSchemaV4Factory();
schemaFactory.setAutoPutDollarSchema(true);
JsonNode fstabSchema = schemaFactory.createSchema(inputObj.getClass());
ArrayList<String> validationErrorDetails = new ArrayList<String>();
// *****************************************************************************************
// /!\ this is an ugly hack /!\
// Randomly the function createSchema() returns an 'array' or 'object' type for coordinates
// of the geoJsonPoint. The correct value should be array. The following code checks if a
// geoJsonPoint is inside the schema and overwrites it with the correct value.
// TODO: fix this issue correctly
// *****************************************************************************************
try {
String jsonCoordinate = "{\"type\": \"array\",\"items\": {\"type\": \"number\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNodeCoordinate = mapper.readTree(jsonCoordinate);
JsonNode coordJsonNode = fstabSchema.findValue("geoPosition").get("properties");
ObjectNode coordObjNode = (ObjectNode) coordJsonNode;
coordObjNode.set("coordinates", jsonNodeCoordinate);
} catch (JsonProcessingException e) {
validationErrorDetails.add("Could not patch geoPosition");
return validationErrorDetails;
} catch (IOException e) {
validationErrorDetails.add("Could not patch geoPosition");
return validationErrorDetails;
} catch (NullPointerException e) {
// this means that geoPosition could not be found
// we do nothing ...
}
// ******************
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
final JsonSchema schema = factory.getJsonSchema(fstabSchema);
ObjectMapper objectMapper = new ObjectMapper();
JsonNode baseReceiptJson = objectMapper.convertValue(inputObj, JsonNode.class);
ProcessingReport report;
report = schema.validate(baseReceiptJson);
if (!report.isSuccess()) {
StringBuilder builder = new StringBuilder();
builder.append("Not all required fields are filled with data");
builder.append(System.getProperty("line.separator"));
for (Iterator<ProcessingMessage> i = report.iterator(); i.hasNext();) {
ProcessingMessage msg = i.next();
builder.append(msg.asJson().findValue("instance").findValue("pointer").toString());
builder.append(": ");
builder.append(msg.getMessage());
String detail = msg.asJson().findValue("instance").findValue("pointer").toString() + ": " + msg.getMessage();
detail = detail.replace("\"", "");
validationErrorDetails.add(detail);
builder.append("\n");
}
return validationErrorDetails;
}
return null;
}
}
By serializing the JSON Schema you generated we are able now to compare whether they are the same or how much they actually differ. Take into account that the method to generate a schema requires some input parameter.
I was never a friend of generating a schema based on actual data.
Why do you not strictly define the schema you want and let your code measure whether you really meet that structure? This way you can use the schema as a contract between application components since it is documented and not generated on the fly.
This is still no answer to the question why this happens randomly. But it is maybe a better practice to follow for you and others reading along.

How to get the last entry of a field in JSON

I use an API from api.nasa.gov that I query using the following Java class to read magnitude information on the latest solar flare of the day.
The response is used to fill in a field on a weather station that informs about current solar hazards.
The problem is that this code only returns the "classType" (magnitude) of first "flrID" (solar flare) event of the day. On July 3, for example, there was more than one event, and the most relevant event is the latest.
I am trying to find out how to get the "classType" of the last "flrID" in the JSON string, given that the flrID text contains an unknown arbitrary time of day.
Secondly, I am not sure how to get event driven updates from NASA, other than from pushed email messages. I am allowed an API request every 3.6 seconds, so that will work, but I am inquiring if there is a less expensive method to get near real time updates from NASA.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import org.json.JSONException;
import org.json.JSONObject;
public class NasaFlrApiReader {
public static final String API_KEY = "DEMO_KEY";
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
try (InputStream is = new URL(url).openStream()) {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
String jsonText = readAll(rd);
int i = jsonText.indexOf("{");
jsonText = jsonText.substring(i);
JSONObject json = new JSONObject(jsonText);
return json;
}
}
public static void main(String[] args) throws IOException, JSONException {
JSONObject json = readJsonFromUrl("https://api.nasa.gov/DONKI/FLR?startDate=2021-07-27-03&endDate=2021-07-03&api_key=" + API_KEY);
System.out.println("Class Type: " + json.get("classType"));
}
}
This is the JSON text that is returned from the above code:
[
{
"flrID": "2021-07-03T02:14:00-FLR-001",
"instruments": [
{
"displayName": "GOES-P: EXIS 1.0-8.0"
}
],
"beginTime": "2021-07-03T02:14Z",
"peakTime": "2021-07-03T02:31Z",
"endTime": "2021-07-03T02:39Z",
"classType": "C5.7",
"sourceLocation": "N23W75",
"activeRegionNum": 12838,
"linkedEvents": [
{
"activityID": "2021-07-03T03:48:00-CME-001"
}
],
"link": "https://kauai.ccmc.gsfc.nasa.gov/DONKI/view/FLR/17197/-1"
},
{
"flrID": "2021-07-03T07:04:00-FLR-001",
"instruments": [
{
"displayName": "GOES-P: EXIS 1.0-8.0"
}
],
"beginTime": "2021-07-03T07:04Z",
"peakTime": "2021-07-03T07:17Z",
"endTime": "2021-07-03T07:22Z",
"classType": "M2.7",
"sourceLocation": "N23W78",
"activeRegionNum": 12838,
"linkedEvents": [
{
"activityID": "2021-07-03T08:00:00-CME-001"
}
],
"link": "https://kauai.ccmc.gsfc.nasa.gov/DONKI/view/FLR/17189/-1"
},
{
"flrID": "2021-07-03T14:18:00-FLR-001",
"instruments": [
{
"displayName": "GOES-P: EXIS 1.0-8.0"
}
],
"beginTime": "2021-07-03T14:18Z",
"peakTime": "2021-07-03T14:29Z",
"endTime": "2021-07-03T14:34Z",
"classType": "X1.5",
"sourceLocation": "N23W80",
"activeRegionNum": 12838,
"linkedEvents": [
{
"activityID": "2021-07-03T14:48:00-CME-001"
}
],
"link": "https://kauai.ccmc.gsfc.nasa.gov/DONKI/view/FLR/17201/-1"
},
{
"flrID": "2021-07-03T16:59:00-FLR-001",
"instruments": [
{
"displayName": "GOES-P: EXIS 1.0-8.0"
}
],
"beginTime": "2021-07-03T16:59Z",
"peakTime": "2021-07-03T17:03Z",
"endTime": "2021-07-03T17:14Z",
"classType": "M1.0",
"sourceLocation": "N23W82",
"activeRegionNum": 12838,
"linkedEvents": [
{
"activityID": "2021-07-03T17:36:00-CME-001"
}
],
"link": "https://kauai.ccmc.gsfc.nasa.gov/DONKI/view/FLR/17208/-1"
}
]
The JSON contains an array so during deseralisation, you need to use JSONArray and then get the last element of the array using length-1,
JSONArray jsonArr = new JSONArray(jsonText);
JSONObject lastObject = (JSONObject) jsonArr.get(jsonArr.length()-1);
If length-1 does not give you the last record then you need to sort the JSONArray based on the required field and then take the first or last based on sorting. You can check the below thread for sorting the JSONArray
How can I sort a JSONArray in JAVA

Parse Json with Children Parameters

I'm a little clueless on this subject, but I'm trying to parse some Json into variables using GSON.
Here's an example of part of the Json I'm trying to parse. The goal is to get an array of objects containing the .ogg path(i.e. "minecraft/sounds/mob/stray/death2.ogg") as well as its corresponding hash variable.
{
"objects": {
"minecraft/sounds/mob/stray/death2.ogg": {
"hash": "d48940aeab2d4068bd157e6810406c882503a813",
"size": 18817
},
"minecraft/sounds/mob/husk/step4.ogg": {
"hash": "70a1c99c314a134027988106a3b61b15389d5f2f",
"size": 9398
}
}
Any help or suggestions on how to get that sort of result with GSON would be appreciated.
Xeyeler , the following is a solution that will work. A better way is to look at how GSON can convert this to an object directly. I have not tried it though
import java.util.Map;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class MainProgram {
public static void main(String[] args) {
String mineCraft = "{ \"objects\": { \"minecraft/sounds/mob/stray/death2.ogg\": { \"hash\": \"d48940aeab2d4068bd157e6810406c882503a813\", \"size\": 18817 }, \"minecraft/sounds/mob/husk/step4.ogg\": { \"hash\": \"70a1c99c314a134027988106a3b61b15389d5f2f\", \"size\": 9398 }}}";
JsonParser parser = new JsonParser();
JsonObject objects = parser.parse(mineCraft).getAsJsonObject().get("objects").getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : objects.entrySet()) {
String oggFileName = entry.getKey();
JsonElement attributes = entry.getValue();
System.out.println(
"Key is " + oggFileName + " and the hash value is " + attributes.getAsJsonObject().get("hash"));
}
}
}

Creating array list of java objects from JSON URL with Gson

I am able to parse the following data into a java object:
{
"name": "testname",
"address": "1337 455 ftw",
"type": "sometype",
"notes": "cheers mate"
}
using this code:
public class Test
{
public static void main (String[] args) throws Exception
{
URL objectGet = new URL("http://10.0.0.4/file.json");
URLConnection yc = objectGet.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
Gson gson = new Gson();
try {
DataO data = new Gson().fromJson(in, DataO.class);
System.out.println(data.getName());
}catch (Exception e) {
e.printStackTrace();
}
}
}
But now I want to store a list of these objects out of the following JSON String:
[
{
"name": "testname",
"address": "1337 455 ftw",
"type": "sometype",
"notes": "cheers mate"
},
{
"name": "SumYumStuff",
"address": "no need",
"type": "clunkdroid",
"notes": "Very inefficient but high specs so no problem."
}
]
Could someone help me modify my code to do this?
You could specify the type to deserialize into as an array or as a collection.
As Array:
import java.io.FileReader;
import com.google.gson.Gson;
public class GsonFoo
{
public static void main(String[] args) throws Exception
{
Data0[] data = new Gson().fromJson(new FileReader("input.json"), Data0[].class);
System.out.println(new Gson().toJson(data));
}
}
class Data0
{
String name;
String address;
String type;
String notes;
}
As List:
import java.io.FileReader;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class GsonFoo
{
public static void main(String[] args) throws Exception
{
List<Data0> data = new Gson().fromJson(new FileReader("input.json"), new TypeToken<List<Data0>>(){}.getType());
System.out.println(new Gson().toJson(data));
}
}
A quick look in the Gson User Guide indicates that this might not be possible since the deserializer doesn't know the type of the elements since you could have elements of different types in the array.
Collections Limitations
Can serialize collection of arbitrary objects but can not deserialize
from it Because there is no way for the user to indicate the type of
the resulting object While deserializing, Collection must be of a
specific generic type

Categories

Resources