How to parse JSON Response with GSON (Java / Android) - java

I just need a quick advice, as i am a total beginner with JSON.
I get the following response from a webserver, which i store in a String:
{
"station62":[
{
"departureTime":1982,
"delay":"-1.0",
"line":"6",
"stationName":"randomname",
"direction":2
}
],
"station63":[
{
"departureTime":1234,
"delay":"-1.0",
"line":"87",
"stationName":"anotherrandomname",
"direction":2
}
],
"station64":[
{
"departureTime":4542,
"delay":"-1.0",
"line":"4",
"stationName":"yetanotherrandomname",
"direction":2
}
],
"station65":[
{
"departureTime":1232,
"delay":"-1.0",
"line":"23",
"stationName":"onemorerandomname",
"direction":2
}
]
}
(Sorry, i dont know how the indent works on here.)
The response is longer, but for this example it is shortened. So what i need is to parse the information of each of these "station"-objects.
I dont need the "station62"-String, i only need "departureTime", "delay", "line", "stationName" and "direction" in a java-object.
I have read this, but i couldnt make it work: https://stackoverflow.com/a/16378782
I am a total beginner, so any help would be really appreciated.
Edit: Here is my code:
I made a wrapper class just like in the example link above. I played with the map types a bit, but no luck so far.
public class ServerResponse
{
private Map<String, ArrayList<Station>> stationsInResponse = new HashMap<String, ArrayList<Station>>();
public Map<String, ArrayList<Station>> getStationsInResponse()
{
return stationsInResponse;
}
public void setStationsInResponse(Map<String, ArrayList<Station>> stationsInResponse)
{
this.stationsInResponse = stationsInResponse;
}
}
The problem is, that this map does not get filled by the gson.fromJSON(...)-call i am showing below. The map size is always zero.
Station class looks like this:
public class Station
{
String line;
String stationName;
String departureTime;
String direction;
String delay;
// getters and setters are there aswell
}
And what i am trying to do is
Gson gson = new Gson();
ServerResponse response = gson.fromJson(jsonString, ServerResponse.class);
where "jsonString" contains the JSON response as a string.
I hope that code shows what i need to do, it should be pretty simple but i am just not good enough in JSON.
EDIT 2
Would i need my JSON to be like this?
{"stationsInResponse": {
"station62": [{
"departureTime": 1922,
"delay": "-1.0",
"line": "8",
"stationName": "whateverrandomname",
"direction": 2
}],
"station67": [{
"departureTime": 1573,
"delay": "-1.0",
"line": "8",
"stationName": "rndmname",
"direction": 2
}],
"station157": [{
"departureTime": 1842,
"delay": "-2.0",
"line": "8",
"stationName": "randomname",
"direction": 2
}]
}}

Here is the working code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
public class GSONTest {
public static void main(String[] args){
String gsonStr = "{\"stationsInResponse\": { \"station62\":[ { \"departureTime\":1982,\"delay\":\"-1.0\",\"line\":\"6\",\"stationName\":\"randomname\",\"direction\":2} ],\"station63\":[ { \"departureTime\":1981,\"delay\":\"-1.1\",\"line\":\"7\",\"stationName\":\"randomname2\",\"direction\":3} ]}}";
Gson gson = new Gson();
Response response = gson.fromJson(gsonStr, Response.class);
System.out.println("Map size:"+response.getStationsInResponse().size());
for (Iterator iterator = response.getStationsInResponse().keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
ArrayList<Station> stationList = (ArrayList<Station>) response.getStationsInResponse().get(key);
for (Iterator iterator2 = stationList.iterator(); iterator2.hasNext();) {
Station station = (Station) iterator2.next();
System.out.println("Delay: "+station.getDelay());
System.out.println("DepartureTime: "+station.getDepartureTime());
System.out.println("Line: "+station.getLine());
System.out.println("StationName: "+station.getStationName());
}
}
}
}
class Response {
private Map<String, List<Station>> stationsInResponse;
//getters and setters
public Map<String, List<Station>> getStationsInResponse() {
return stationsInResponse;
}
public void setStationsInResponse(Map<String, List<Station>> stationsInResponse) {
this.stationsInResponse = stationsInResponse;
}
}
class Station {
private String departureTime;
public String getDepartureTime() {
return departureTime;
}
public void setDepartureTime(String departureTime) {
this.departureTime = departureTime;
}
public String getDelay() {
return delay;
}
public void setDelay(String delay) {
this.delay = delay;
}
public String getLine() {
return line;
}
public void setLine(String line) {
this.line = line;
}
public String getStationName() {
return stationName;
}
public void setStationName(String stationName) {
this.stationName = stationName;
}
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
private String delay;
private String line;
private String stationName;
private String direction;
}
Output in console is like this(as I shortened your json string):
Map size:2
Delay: -1.0
DepartureTime: 1982
Line: 6
StationName: randomname
Delay: -1.1
DepartureTime: 1981
Line: 7
StationName: randomname2

First I'll point out your mistake, then I'll give you the solution.
The structure you're asking for in your deserialization code looks like this:
{
"stationsInResponse": {
"station1": [
{
"name": "Station 1"
}
],
"station2": [
{
"name": "Station 2"
}
]
}
}
Solution
The deserialization code you really need to deserialize the structure you're getting as input, is as follows:
Gson gson = new Gson();
Type rootType = new TypeToken<Map<String, List<Station>>>(){}.getType();
Map<String, List<Station>> stationsMap = gson.fromJson(json, rootType);
This is because a JSON object, whose properties are unknown at compile-time, which your root object is, maps to a Java Map<String, ?>. The ? represent the expected Java type of the JSON object value, which in your case is either List<Station> or Station[], whichever you prefer.
If you wanted to, you could combine all the stations in the map into one List of stations like so:
List<Station> stations = new ArrayList<>(stationsMap.size());
for (List<Station> stationsList : stationsMap.values()) {
for (Station station : stationsList) {
stations.add(station);
}
}

Related

Reformat JSON arrays/object in java

I am trying to reformat this json file to a different format. I never used jackson or gson before. I get the idea of it but I don't know how to implement it.
So what I have is a json file: file.json that contains:
{
"Fruits": [
{
"name": "avocado",
"organic": true
},
{
"name": "mango",
"organic": true
}
]
}
What I want is to get in this format:
{
"List Fruits":{
"Fruits": [
{
"name": "avocado",
"organic": true
},
{
"name": "mango",
"organic": true
}
]
}
}
Somehow add the "List Fruits" in the json file.
I am trying to use the jackson api but I don't know how.
Assign the JSON to String variable, for example assign the above JSON to variable called json:
String json = "..." // here put your JSON text;
Prepare classes for your objects:
class Fruit {
private String name;
private boolean organic;
}
class Fruits {
private List<Fruit> fruits;
}
then use Gson to convert JSON to your objects:
Gson gson = new Gson();
Fruits fruits = gson.fromJson(json, Fruits.class);
Next prepare wrapper class ListOfFruits for your fruits object:
class ListOfFruits {
private Fruits listOfFruits;
public ListOfFruits(Fruits fruits) {
listOfFruits = fruits;
}
}
Next pack your fruits object into another one:
ListOfFruits lof = new ListOfFruits(fruits);
And finally generate back the output JSON:
String newJson = gson.toJson(lof);
You do not need to create POJO model for reading and updating JSON. Using Jackson, you can read whole JSON payload to JsonNode, create a Map with required key and serialising to JSON back. See below example:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.util.Collections;
import java.util.Map;
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);
JsonNode root = mapper.readTree(jsonFile);
Map<String, JsonNode> output = Collections.singletonMap("List Fruits", root);
System.out.println(mapper.writeValueAsString(output));
}
}
Above code prints:
{
"List Fruits" : {
"Fruits" : [ {
"name" : "avocado",
"organic" : true
}, {
"name" : "mango",
"organic" : true
} ]
}
}
I would highly recommend going through the documentations of Jackson or Gson libraries as you mentioned you are new.
I have created a sample git repo for this item. This sample uses Jackson API.
Visit https://github.com/rajramo61/jsonwrapper
final InputStream fileData = ClassLoader.getSystemResourceAsStream("file.json");
ObjectMapper mapper = new ObjectMapper();
InitialJson initialJson = mapper.readValue(fileData, InitialJson.class);
System.out.println(mapper.writeValueAsString(initialJson));
final FinalJson finalJson = new FinalJson();
finalJson.setListOfFruits(initialJson);
System.out.println(mapper.writeValueAsString(finalJson));
This is the Fruit class.
public class Fruit {
private String name;
private boolean organic;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean getOrganic() {
return organic;
}
public void setOrganic(boolean organic) {
this.organic = organic;
}
#Override
public String toString() {
return "Fruit{" +
"name='" + name + '\'' +
", organic=" + organic +
'}';
}
}
Here is FinalJson class detail. This is the class will wrap the initial json loaded from jsn file.
public class FinalJson {
private InitialJson listOfFruits;
#JsonProperty("List Fruits")
public InitialJson getListOfFruits() {
return listOfFruits;
}
public void setListOfFruits(InitialJson listOfFruits) {
this.listOfFruits = listOfFruits;
}
}
Here is InitialJson class detail. This is the class pulls data from json file.
public class InitialJson {
private List<Fruit> fruits;
#JsonProperty("Fruits")
public List<Fruit> getFruits() {
return fruits;
}
public void setFruits(List<Fruit> fruits) {
this.fruits = fruits;
}
#Override
public String toString() {
return "InitialJson{" +
"fruits=" + fruits +
'}';
}
}
You can fork the repo and close this in local and it should work fine.

How to add elements to json array from Java interface at run time

I want to add the elements to JSON array from the Java GUI at runtime
but every time the new array is created in JSON file
Java GUI to enter data:
String _itemType = txtItemType.getText();
int _itemQuantity = Integer.parseInt(txtItemQuantity.getText());
JSONWriteExample obj = new JSONWriteExample(_itemType, _itemQuantity);
obj.jsonParse();
JSON:
public JSONWriteExample(String type, int number) {
this.type = type;
this.quantity = number;
}
public void jsonParse() throws IOException {
JSONObject jo = new JSONObject();
Map m = new LinkedHashMap(4);
JSONArray ja = new JSONArray();
m = new LinkedHashMap(2);
m.put("Item Type", type);
m.put("Quantity", quantity);
ja.add(m);
jo.put("Items", ja);
FileWriter file=new FileWriter("jsonArray.json",true);
file.append(jo.toString());
file.flush();
file.close();
}
I expect the output like:
{
"Items":[
{
"Item Type":"TV",
"Quantity":3
},
{
"Item Type":"phone",
"Quantity":3
}
]
}
But new array is created each time like:
{
"Items":[
{
"Item Type":"TV",
"Quantity":3
}
]
}{
"Items":[
{
"Item Type":"phone",
"Quantity":3
}
]
}
As #fabian mentioned in the comment - you should first parse the file content, modify and overwrite the file. Here is a sample code how to achieve that:
First of all, I don't know what json library you're using, but I would strongly suggest to use the following:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
It will generally ease your work with json. If you don't want to use libraries you can still follow the instruction, but adapt it for your needs. The whole implementation is like this:
public class JSONWriteExample {
private static final String FILE_NAME = "jsonArray.json";
private static final Path FILE_PATH = Paths.get(FILE_NAME);
private final String type;
private final int quantity;
public JSONWriteExample(String type, int quantity) {
this.type = type;
this.quantity = quantity;
}
public void jsonParse() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
if (Files.notExists(FILE_PATH)) {
Files.createFile(FILE_PATH);
objectMapper.writeValue(FILE_PATH.toFile(), createItems(new ArrayList<>()));
}
Items items = objectMapper.readValue(FILE_PATH.toFile(), Items.class);
final List<Item> itemsList = items.getItems();
objectMapper.writeValue(FILE_PATH.toFile(), createItems(itemsList));
}
private Items createItems(List<Item> itemsList) {
final Item item = new Item();
item.setType(type);
item.setQuantity(quantity);
itemsList.add(item);
final Items items = new Items();
items.setItems(itemsList);
return items;
}
public static class Items {
private List<Item> items;
// Setters, Getters
}
public static class Item {
private String type;
private int quantity;
// Setters, Getters
}
}
Okay, what's going on in this code?
First of all, note the usage of Java 7 NIO - recommended way to work with files in java.
In jsonParse method we first check if file exists.
If it does - then we read it to the data class (Items) that describes our model. The reading part is done under the hood of this library, just the fileds of your json file should have the same names as the fields of the data classes (or specified with JsonAlias annotation.
If it doesn't - then we create it first and populate with the initial values.
ObjectMapper is the class from the library and it's used to read\write json files.
Now if we run this piece of code, e.g.
public static void main(String[] args) throws IOException {
JSONWriteExample example = new JSONWriteExample("TV", 3);
example.jsonParse();
JSONWriteExample example2 = new JSONWriteExample("phone", 3);
example2.jsonParse();
}
json file will look like:
{
"items": [
{
"type": "TV",
"quantity": 3
},
{
"type": "TV",
"quantity": 3
},
{
"type": "phone",
"quantity": 3
}
]
}

Using jackson to extract inner JSON array list

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.

How do I make nested JSON Objects using Gson?

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];
}
}
}

Jackson JsonParser fails reading an array in Json

I have a Json Structure something like this
{
"name" : "abcd",
"details" : [{"city":"string", "zipcode":"integer"}],
"name" : "qwert",
"details" : [{"address":"long", "state":"string"}]
}
And my java code looks like below
public class JsonTest {
public static void main(String[] args) throws JsonParseException, IOException {
JsonFactory jf = new JsonFactory();
JsonParser jp = jf.createParser(new File("C:\\sample.json"));
while (jp.nextToken() != JsonToken.END_OBJECT)
{
String jsonField = jp.getCurrentName();
if ("name".equalsIgnoreCase(jsonField))
{
jp.nextToken();
System.out.println(jp.getText());
}
if ("details".equalsIgnoreCase(jsonField))
{
jp.nextToken();
while (jp.nextToken() != JsonToken.END_ARRAY)
{
jp.nextToken();
String field = jp.getText();
System.out.println(field);
}
}
}
}
}
All am trying to do is parse the whole json token by token and get the text. But the line while (jp.nextToken() != JsonToken.END_OBJECT) fails when it encounters a '}' in the array. Am just stuck here since yesterday and experimenting with several other tricks but nothing works out. Do we have another way doing this? Is my JSON structure looks okay? Please tell me where am going wrong. Thanks!
First of all:
[Doe]s my JSON structure look[s] okay?
Yes and no. while your JSON is legal, you are going to have a problem because of duplicate keys:
{
"name": "xxx",
"name": "yyy"
}
The behaviour of a JSON parser in this event is unpredictable, even RFC 7159 says so (yes, RFC 4627 has been superseded). Unfortunately, duplicate keys are still not forbidden.
So, it is legal, but not sane. Use an array instead:
[ { "name": "xxx", "details": "whatever" }, "etc" ]
This aside, reading JSON with Jackson is done as this:
final ObjectMapper mapper = new ObjectMapper();
final JsonNode node = mapper.readTree(yourFileHere);
You can then use the full power of JsonNode.
You cannot have fields with the same name in a json, well you can but it could not be parsed as in your case.
I assume you have an array of users with name and details fileds for each user.
Here is a candidate Java class corresponding to your User class:
public class TestUser implements Serializable {
String name;
List<Map<String, String>> details = new ArrayList<Map<String, String>>();
TestUser() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Map<String, String>> getDetails() {
return details;
}
public void setDetails(List<Map<String, String>> details) {
this.details = details;
}
}
with reverse engineering lets see how is a list of users are de-serialized;
public static void main(String[] args) throws IOException {
List<TestUser> testUsers = new ArrayList<TestUser>();
TestUser testUser1 = new TestUser();
testUser1.name = "abcd";
HashMap<String, String> detailsHashMap = new HashMap<String, String>();
detailsHashMap.put("city", "string");
detailsHashMap.put("zipcode", "integer");
testUser1.details.add(detailsHashMap);
testUsers.add(testUser1);
TestUser testUser2 = new TestUser();
testUser2.name = "qwert";
detailsHashMap = new HashMap<String, String>();
detailsHashMap.put("address", "long");
detailsHashMap.put("state", "string");
testUser2.details.add(detailsHashMap);
testUsers.add(testUser2);
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(testUsers));
}
and the outcome of the users list is:
[ {
"name" : "abcd",
"details" : [ {
"zipcode" : "integer",
"city" : "string"
} ]
}, {
"name" : "qwert",
"details" : [ {
"address" : "long",
"state" : "string"
} ]
} ]
As you can see it is different from your JSON string.
UPDATE
If you want to hold names and details in two separate containers...;
public static class Container {
List<String> names = new ArrayList<String>();
Map<String, String> details = new HashMap<String, String>();
public Container() {
}
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
public Map<String, String> getDetails() {
return details;
}
public void setDetails(Map<String, String> details) {
this.details = details;
}
}
....
public static void main(String[] args) throws IOException {
Container container = new Container();
container.names.add("abcd");
container.names.add("qwert");
container.details.put("city", "string");
container.details.put("zipcode", "integer");
container.details.put("address", "long");
container.details.put("state", "string");
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(container));
}
and the outcome JSON is;
{
"names" : [ "abcd", "qwert" ],
"details" : {
"address" : "long",
"zipcode" : "integer",
"state" : "string",
"city" : "string"
}
}

Categories