JSON formatting for a Java Server - java

I am trying to read JSON string using gson into a Java program. In the sample code below - the Java program has 3 object classes. The data in the json string will have a variable number of object instances of each class. I have tried to create a sample JSON - to parse .. but had problems parsing the various objects.
Is this the right way to consume a json string or can it be done in a different way.. How would you parse a json with variable objects of different classes. Thanks,
package newpackage;
import java.util.ArrayList;
import com.google.gson.Gson;
public class jsonsample {
public static void main(String[] args) {
String jsonstring = "{'TableA':[{'field_A1':'A_11'},{'field_A1':'A_12'}]}"
+ ",{'TableB':[{'field_B1':'B_11','field_B2':'B_12','field_B3':['abc','def','ghi']},"
+ "{'field_B1':'B_21','field_B2':'B_Field22','field_B3':['mno','pqr','xyz']}]"
+ ",{'TableC':[{'field_C1':'C_11','field_C2':'C_12','field_C3':'C_13'},"
+ "{'field_C1':'C_21','field_C2':'C_22','field_C3':'C_23'},{'field_C1':'C_31','field_C2':'C_32','field_C3':'C_33'}]}";
jsonstring = jsonstring.replace('\'', '"');
}
public class TableA {
String field_A1;
public TableA(String a){
this.field_A1 = a;
}
#Override
public String toString() {
return ("Table A" + " " + this.field_A1);
}
}
public class TableB {
String field_B1;
String field_B2;
ArrayList<String> field_B3 = new ArrayList<String>();
public TableB(String a, String b, ArrayList<String> c){
this.field_B1 = a;
this.field_B2 = b;
this.field_B3 = c;
}
#Override
public String toString() {
return ("Table B" + " " + this.field_B1+ " " + this.field_B2);
}
}
public class TableC {
String field_C1;
String field_C2;
String field_C3;
public TableC(String a, String b, String c){
this.field_C1 = a;
this.field_C2 = b;
this.field_C3 = c;
}
#Override
public String toString() {
return ("Table C" + " " + this.field_C1 + " " + this.field_C2 + " " + this.field_C3);
}
}
}

First of all you have to decide what is your base json structure ? Max identifiers, max values, max objects,max arrays...
Create your full json structure with texteditor or http://www.jsoneditoronline.org/ or http://jsonlint.com/ etc.
Let's think this is my full json structure:
{
"array": [
1,
2,
3
],
"boolean": true,
"null": null,
"number": 123,
"object": {
"a": "b",
"c": "d",
"e": "f"
},
"string": "Hello World"
}
Create your Java Classes as like as your json identifiers. You can use http://json2csharp.com/ convert to Java.
And these are my Java Classes:
public class Object
{
public string a { get; set; }
public string c { get; set; }
public string e { get; set; }
}
public class RootObject
{
public ArrayList<int> array { get; set; }
public Boolean boolean { get; set; }
public Object #null { get; set; }
public int number { get; set; }
public Object #object { get; set; }
public string #string { get; set; }
}
Create your DAO for convert these to structure to them.
For Java;
String data = "jsonString";
RootObject root = new GsonBuilder().create().fromJson(data, RootObject.class);
For Json;
Gson gson = new GsonBuilder().setDateFormat("dd/MM/yyyy").create();
String json = gson.toJson(obj);

Your JSON-string seems incorrect to me. Let me propose the following:
public static void main(String args[]) {
String jsonstring = "["
+ "{'TableA':[{'field_A1':'A_11'},{'field_A1':'A_12'}]}"
+ ",{'TableB':[{'field_B1':'B_11','field_B2':'B_12','field_B3':['abc','def','ghi']},"
+ "{'field_B1':'B_21','field_B2':'B_Field22','field_B3':['mno','pqr','xyz']}]}"
+ ",{'TableC':[{'field_C1':'C_11','field_C2':'C_12','field_C3':'C_13'},"
+ "{'field_C1':'C_21','field_C2':'C_22','field_C3':'C_23'},{'field_C1':'C_31','field_C2':'C_32','field_C3':'C_33'}]}"
+ "]";
jsonstring = jsonstring.replace('\'', '"');
Gson gson = new Gson();
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(jsonstring).getAsJsonArray();
for (JsonElement jsonElement : array) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
Map.Entry<String,JsonElement> table = jsonObject.entrySet().iterator().next();
String tableName = table.getKey();
JsonElement rows = table.getValue();
try {
Class<?> rowClass = Class.forName("[Lnewpackage." + tableName + ";"); // explanation see below this code snippet
// rowClass is an array class!
Object[] parsedRows = gson.fromJson(rows, rowClass);
// do something with parsedRows
for (Object x : parsedRows) {
System.out.println(x);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Assuming a "table definition" consists of a property named as the class ob the objects in the table, with the objects as array value of that property.
Explanation of Class.forName("[Lnewpackage." + tableName + ";")
This retrieves the Class instance for the array type of a class located in the package newpackage, e.g. newpackage.TableA[] (note the []). Class.forName("A") returns the instance representing the class A. Class.forName("[LA;") returns the instance representing the "class" of an array of As. Using it as a parameter for fromJson(...) it results in the parsing of a JSON array of A-objects.

This is the code - that works based on #hurricane suggestion.
package newpackage;
import java.util.List;
import com.google.gson.*;
public class jsonsample {
public static void main(String[] args) throws ClassNotFoundException {
String jsonstring = "{'TableA':["
+ "{'field_A1':'A_11'},"
+ "{'field_A1':'A_12'}"
+ "],"
+ "'TableB':["
+ "{'field_B1':'B_11','field_B2':'B_12','field_B3':['abc','def']},"
+ "{'field_B1':'B_21','field_B2':'B_22','field_B3':['mno','xyz']}"
+ "],"
+ "'TableC':["
+ "{'field_C1':'C_11','field_C2':'C_12','field_C3':'C_13'},"
+ "{'field_C1':'C_21','field_C2':'C_22','field_C3':'C_23'}"
+ "]}";
jsonstring = jsonstring.replace('\'', '"');
RootObject root = new GsonBuilder().create().fromJson(jsonstring, RootObject.class);
for (int i=0; i < root.TableA.size(); i++){
System.out.println(root.TableA.get(i));
}
for (int i=0; i < root.TableB.size(); i++){
System.out.println(root.TableB.get(i));
}
for (int i=0; i < root.TableC.size(); i++){
System.out.println(root.TableC.get(i));
}
}
public class TableA
{
public String field_A1;
#Override
public String toString() {
return ("Table A" + " " + this.field_A1);
}
}
public class TableB{
public String field_B1;
public String field_B2;
public List<String> field_B3;
#Override
public String toString() {
return ("Table B" + " " + this.field_B1 + " " + this.field_B2 + " " + this.field_B3);
}
}
public class TableC{
public String field_C1;
public String field_C2;
public String field_C3;
#Override
public String toString() {
return ("Table C" + " " + this.field_C1 + " " + this.field_C2 + " " + this.field_C3);
}
}
public class RootObject{
public List<TableA> TableA;
public List<TableB> TableB;
public List<TableC> TableC;
}
}
The output for the above is:
Table A A_11
Table A A_12
Table B B_11 B_12 [abc, def]
Table B B_21 B_22 [mno, xyz]
Table C C_11 C_12 C_13
Table C C_21 C_22 C_23

Related

How to parse array of numeric values in a JSON to Java object with Jsonb

I love how easy it is to map JSON data to a Java object with Jsonb, but I seem to have stumbled upon a not well-documented use-case...
Given this json data:
{
"id": "test",
"points": [
[
-24.787439346313477,
5.5551919937133789
],
[
-23.788913726806641,
6.7245755195617676
],
[
-22.257251739501953,
7.2461895942687988
]
]
}
What can be used as the object type to store the points-values?
import jakarta.json.bind.annotation.JsonbProperty;
public class Temp {
#JsonbProperty("id")
private String id;
#JsonbProperty("points")
private ??? points;
// Getters-Setters
}
So I can create the Temp-object with:
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
Jsonb jsonb = JsonbBuilder.create();
Temp temp = jsonb.fromJson(jsonString, Temp.class);
So far I've tried the following:
List<Point> --> "Can't deserialize JSON array into: class java.awt.Point"
List<Point2D> --> "Can't deserialize JSON array into: class java.awt.Point2D"
Let's try it:
#Data
public class Temp {
#JsonbProperty("id")
private String id;
#JsonbProperty("points")
private List<List<BigDecimal>> points;
public static void main(String[] args) {
String jsonString = "{\n" +
" \"id\": \"test\",\n" +
" \"points\": [\n" +
" [\n" +
" -24.787439346313477,\n" +
" 5.5551919937133789\n" +
" ],\n" +
" [\n" +
" -23.788913726806641,\n" +
" 6.7245755195617676\n" +
" ],\n" +
" [\n" +
" -22.257251739501953,\n" +
" 7.2461895942687988\n" +
" ]\n" +
" ]\n" +
"}";
Jsonb jsonb = JsonbBuilder.create();
Temp temp = jsonb.fromJson(jsonString, Temp.class);
System.out.println(temp);
}
}
To figure out the default mapping, use a non-generic field and observe it with the debugger:
public class Test {
public static void main(String[] args) {
String json = "{\"id\":\"test\",\"points\":[[-24.787439346313477,5.555191993713379],[-23.78891372680664,6.724575519561768],[-22.257251739501953,7.246189594268799]]}";
Temp temp = JsonbBuilder.create().fromJson(json, Temp.class);
System.out.println(temp.points);
}
public static class Temp {
public String id = null;
public List points = null;
public Temp() {
}
}
}
Since I've already done it: Changing the json format would allow this:
public class Test {
public static void main(String[] args) {
String json = "{\"id\":\"test\",\"points\":[ {\"x\" : 1.0, \"y\" : 2.0 }, {\"x\" : 3.0, \"y\" : 4.0 } ] }";
Temp temp = JsonbBuilder.create().fromJson(json, Temp.class);
System.out.println(temp.points);
}
public static class Temp {
public String id = null;
public List<Point> points = null;
public Temp() { }
}
public static class Point {
public double x;
public double y;
public Point() { }
}
}

Query a JSON file with Java-Large file

I am trying to parse below JSON file using java.
I need to be able to
search the file by id or name or any of the fields in the object.
search for empty values in the field as well.
The search should return entire object.
The File will be huge and the search should still be time efficient.
[
{
"id": 1,
"name": "Mark Robb",
"last_login": "2013-01-21T05:13:41 -11:30",
"email": "markrobb#gmail.com",
"phone": "12345",
"locations": [
"Germany",
"Austria"
]
},
{
"id": 2,
"name": "Matt Nish",
"last_login": "2014-02-21T07:10:41 -11:30",
"email": "mattnish#gmail.com",
"phone": "456123",
"locations": [
"France",
"Italy"
]
}
]
This is what I have tried so far using Jackson library.
public void findById(int id) {
List<Customer> customers = objectMapper.readValue(new File("src/main/resources/customers.json"), new TypeReference<List<Customer>>(){});
for(Customer customer: customers) {
if(customer.getId() == id) {
System.out.println(customer.getName());
}
}
}
I just don't think this is an efficient method for a huge JSON file(About 20000 customers in a file). And there could be multiple files. Search time should not increase linearly.
How can I make this time efficient? Should I use any other library?
The most efficient (both CPU and memory) way to parse is to use stream oriented parsing instead of object mapping. Usually, it takes a bit more code to be written, but also usually it is a good deal :) Both Gson and Jackson support such lightweight technique. Also, you should avoid memory allocation in the main/hot path to prevent GC pauses. To illustrate the idea I use a small GC-free library https://github.com/anatolygudkov/green-jelly:
import org.green.jelly.*;
import java.io.CharArrayReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
public class SelectById {
public static class Customer {
private long id;
private String name;
private String email;
public void clear() {
id = 0;
name = null;
email = null;
}
public Customer makeCopy() {
Customer result = new Customer();
result.id = id;
result.name = name;
result.email = email;
return result;
}
#Override
public String toString() {
return "Customer{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
'}';
}
}
public static void main(String[] args) throws Exception {
final String file = "\n" +
"[\n" +
" {\n" +
" \"id\": 1,\n" +
" \"name\": \"Mark Robb\",\n" +
" \"last_login\": \"2013-01-21T05:13:41 -11:30\",\n" +
" \"email\": \"markrobb#gmail.com\",\n" +
" \"phone\": \"12345\",\n" +
" \"locations\": [\n" +
" \"Germany\",\n" +
" \"Austria\"\n" +
" ]\n" +
"},\n" +
" {\n" +
" \"id\": 2,\n" +
" \"name\": \"Matt Nish\",\n" +
" \"last_login\": \"2014-02-21T07:10:41 -11:30\",\n" +
" \"email\": \"mattnish#gmail.com\",\n" +
" \"phone\": \"456123\",\n" +
" \"locations\": [\n" +
" \"France\",\n" +
" \"Italy\"\n" +
" ]\n" +
" }\n" +
"]\n";
final List<Customer> selection = new ArrayList<>();
final long selectionId = 2;
final JsonParser parser = new JsonParser().setListener(
new JsonParserListenerAdaptor() {
private final Customer customer = new Customer();
private String currentField;
#Override
public boolean onObjectStarted() {
customer.clear();
return true;
}
#Override
public boolean onObjectMember(final CharSequence name) {
currentField = name.toString();
return true;
}
#Override
public boolean onStringValue(final CharSequence data) {
switch (currentField) {
case "name":
customer.name = data.toString();
break;
case "email":
customer.email = data.toString();
break;
}
return true;
}
#Override
public boolean onNumberValue(final JsonNumber number) {
if ("id".equals(currentField)) {
customer.id = number.mantissa();
}
return true;
}
#Override
public boolean onObjectEnded() {
if (customer.id == selectionId) {
selection.add(customer.makeCopy());
return false; // we don't need to continue
}
return true;
}
}
);
// now let's read and parse the data with a buffer
final CharArrayCharSequence buffer = new CharArrayCharSequence(1024);
try (final Reader reader = new CharArrayReader(file.toCharArray())) { // replace by FileReader, for example
int len;
while((len = reader.read(buffer.getChars())) != -1) {
buffer.setLength(len);
parser.parse(buffer);
}
}
parser.eoj();
System.out.println(selection);
}
}
It should work almost as fast as possible in Java (in case we cannot use SIMD instructions directly). To get rid of memory allocation at all (and GC pauses) in the main path, you have to replace ".toString()" (it creates new instance of String) by something reusable like StringBuilder.
The last thing which may affects overall performance is method of the file reading. And RandomAccessFile is one of the best options we have in Java. Since your encoding seems to be ASCII, just cast byte to char to pass to the JsonParser.
It should be possible to do this with Jackson. The trick is to use JsonParser to stream/parse the top-level array and then parse each record using ObjectMapper.readValue().
ObjectMapper objectMapper = new ObjectMapper();
File file = new File("customers.json");
try (JsonParser parser = objectMapper.getFactory().createParser(file))
{
//Assuming top-level array
if (parser.nextToken() != JsonToken.START_ARRAY)
throw new RuntimeException("Expected top-level array in JSON.");
//Now inside the array, parse each record
while (parser.nextToken() != JsonToken.END_ARRAY)
{
Customer customer = objectMapper.readValue(parser, Customer.class);
//Do something with each customer as it is parsed
System.out.println(customer.id + ": " + customer.name);
}
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Customer
{
public String id;
public String name;
public String email;
}
In terms of time efficiency it will need to still scan the entire file - not much you can do about that without an index or something fancier like parallel parsing. But it will be more memory efficient than reading the entire JSON into memory - this code only loads one Customer object at a time.
Also:
if(customer.getId() == id) {
Use .equals() for comparing strings, not ==:
if (customer.getId().equals(id)) {
You can try the Gson library. This library implements a TypeAdapter class that converts Java objects to and from JSON by streaming serialization and deserialization.
The API is efficient and flexible especially for huge files. Here is an example:
public class GsonStream {
public static void main(String[] args) {
Gson gson = new Gson();
try (Reader reader = new FileReader("src/main/resources/customers.json")) {
Type listType = new TypeToken<List<Customer>>(){}.getType();
// Convert JSON File to Java Object
List<Customer> customers = gson.fromJson(reader, listType);
List<Customer> names = customers
.stream()
.filter(c -> c.getId() == id)
.map(Customer::getName)
.collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
}
}
If you want to understand how to Override the TypeAdapter abstract class here you have and example:
public class GsonTypeAdapter {
public static void main(String args[]) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Customer.class, new customerAdapter());
builder.setPrettyPrinting();
Gson gson = builder.create();
try {
reader = new JsonReader(new FileReader("src/main/resources/customers.json"));
Customer customer = gson.fromJson(jsonString, Customer.class);
System.out.println(customer);
jsonString = gson.toJson(customer);
System.out.println(jsonString);
} catch (IOException e) {
e.printStackTrace();
}
}
}
class customerAdapter extends TypeAdapter<Customer> {
#Override
public customer read(JsonReader reader) throws IOException {
Customer customer = new customer();
reader.beginObject();
String fieldName = null;
while (reader.hasNext()) {
JsonToken token = reader.peek();
if (token.equals(JsonToken.NAME)) {
//get the current token
fieldName = reader.nextName();
}
if ("name".equals(fieldName)) {
//move to next token
token = reader.peek();
customer.setName(reader.nextString());
}
if("id".equals(fieldName)) {
//move to next token
token = reader.peek();
customer.setRollNo(reader.nextInt());
}
}
reader.endObject();
return customer;
}
#Override
public void write(JsonWriter writer, Customer customer) throws IOException {
writer.beginObject();
writer.name("name");
writer.value(customer.getName());
writer.name("id");
writer.value(customer.getId());
writer.endObject();
}
}
class Customer {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "Customer[ name = " + name + ", id: " + id + "]";
}
}

How to provide Object as well as String in the data provider for TestNG

I have few dependent TCs grouped together.
The TC2 has some data of its own and also dependent on some of the data from TC1.
I am unable to provide an array of Object along with String in the data provider.
I tried by providing a mix of Object and String in data provider.
#DataProvider(name="mydataprovider")
protected Object[][] dataprovider(){
Object[][] returnObj = new Object[this.classObject.size()][];
for(int index=0; index < this.classObject.size(); index++) {
returnObj[index] = new Object[]{this.classObject.get(index)};
}
return new Object[][]{
{"name","position"}, {returnObj}
};
}
#Test(dataProvider="mydataprovider", dependsOnMethods = {"TC1"})
public void testMethod(String name, String position, MyClassData classData)
{
//Test Steps
}
I am facing the issue of Data provider mismatch
org.testng.internal.reflect.MethodMatcherException
You can pass anything to the methods, a simplified version of your code.
class MyClassData {
String abc;
MyClassData(String abc) {
this.abc = abc;
}
#Override
public String toString() {
return "MyClassData [abc=" + abc + "]";
}
}
#DataProvider(name="mydataprovider")
protected Object[][] dataprovider(){
MyClassData[] obj = new MyClassData[2];
obj[0] = new MyClassData("abc");
obj[1] = new MyClassData("def");
return new Object[][]{
{"name","position", obj}
};
//If you want to pass one obj as one param then, in which case your test method should accept MyClassData object instead of MyClassData[]
return new Object[][]{
{"name","position", obj[0]},
{"name","position", obj[1]},
};
}
#Test(dataProvider="mydataprovider")
public void testMethod(String name, String position, MyClassData[] classData)
{
System.out.println(name + " " + position + " " + classData[0]);
System.out.println(name + " " + position + " " + classData[1]);
//Test Steps
}

How to get each value from JSON string

I have this JSON String and I need to get each docmanId and each dz so,I could loop through them and work with them.
I have tried using gson library to do that,but I dont seem to figure it out.
JSON Array :
[{"docmanId":1,"dz":"CR"},
{"docmanId":1,"dz":"EU"},
{"docmanId":1,"dz":"JD"},
{"docmanId":1,"dz":"LT"},
{"docmanId":10,"dz":"CR"},
{"docmanId":10,"dz":"EU"},
{"docmanId":10,"dz":"LT"},
{"docmanId":100,"dz":"CR"},
{"docmanId":100,"dz":"EU"},
{"docmanId":100,"dz":"JD"},
{"docmanId":100,"dz":"LT"},
{"docmanId":1000,"dz":"CR"},
{"docmanId":1000,"dz":"EU"},
{"docmanId":1000,"dz":"JD"},
{"docmanId":1000,"dz":"LT"},
{"docmanId":10000,"dz":"ES"},
{"docmanId":10000,"dz":"EU"},
{"docmanId":10000,"dz":"JD"},
{"docmanId":100000,"dz":"CR"},
{"docmanId":100000,"dz":"EU"},
{"docmanId":100000,"dz":"JD"},
{"docmanId":100000,"dz":"LT"},
{"docmanId":100001,"dz":"CR"},
{"docmanId":100001,"dz":"EU"},
{"docmanId":100001,"dz":"LT"},
{"docmanId":100002,"dz":"CR"},
{"docmanId":100002,"dz":"EU"},
{"docmanId":100002,"dz":"JD"},
{"docmanId":100003,"dz":"CR"},
{"docmanId":100003,"dz":"EU"},
{"docmanId":100003,"dz":"JD"},
{"docmanId":100003,"dz":"LT"},
{"docmanId":100004,"dz":"CR"},
{"docmanId":100004,"dz":"EU"},
{"docmanId":100004,"dz":"JD"},
{"docmanId":100005,"dz":"CR"},
{"docmanId":100005,"dz":"EU"},
{"docmanId":100005,"dz":"JD"},
{"docmanId":100005,"dz":"LT"},
{"docmanId":100006,"dz":"CR"},
{"docmanId":100006,"dz":"EU"},
{"docmanId":100006,"dz":"JD"},
{"docmanId":100006,"dz":"LT"},
{"docmanId":100007,"dz":"CR"},
{"docmanId":100007,"dz":"EU"},
{"docmanId":100007,"dz":"JD"}]
With org.json ,
JSONArray jSONArray = new JSONArray("your input array");
int length = jSONArray.length();
for (int i = 0; i < length; i++) {
JSONObject jSONObject= jSONArray.getJSONObject(i);
System.out.println(jSONObject.get("docmanId"));
System.out.println(jSONObject.get("dz"));
}
with jackson
String json = "[{\"docmanId\":1,\"dz\":\"CR\"},\n" +
"{\"docmanId\":1,\"dz\":\"EU\"},\n" +
"{\"docmanId\":1,\"dz\":\"JD\"},\n" +
"{\"docmanId\":1,\"dz\":\"LT\"},\n" +
"{\"docmanId\":10,\"dz\":\"CR\"},\n" +
"{\"docmanId\":10,\"dz\":\"EU\"},\n" +
"{\"docmanId\":10,\"dz\":\"LT\"},\n" +
"{\"docmanId\":100,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100,\"dz\":\"JD\"},\n" +
"{\"docmanId\":100,\"dz\":\"LT\"},\n" +
"{\"docmanId\":1000,\"dz\":\"CR\"},\n" +
"{\"docmanId\":1000,\"dz\":\"EU\"},\n" +
"{\"docmanId\":1000,\"dz\":\"JD\"},\n" +
"{\"docmanId\":1000,\"dz\":\"LT\"},\n" +
"{\"docmanId\":10000,\"dz\":\"ES\"},\n" +
"{\"docmanId\":10000,\"dz\":\"EU\"},\n" +
"{\"docmanId\":10000,\"dz\":\"JD\"},\n" +
"{\"docmanId\":100000,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100000,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100000,\"dz\":\"JD\"},\n" +
"{\"docmanId\":100000,\"dz\":\"LT\"},\n" +
"{\"docmanId\":100001,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100001,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100001,\"dz\":\"LT\"},\n" +
"{\"docmanId\":100002,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100002,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100002,\"dz\":\"JD\"},\n" +
"{\"docmanId\":100003,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100003,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100003,\"dz\":\"JD\"},\n" +
"{\"docmanId\":100003,\"dz\":\"LT\"},\n" +
"{\"docmanId\":100004,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100004,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100004,\"dz\":\"JD\"},\n" +
"{\"docmanId\":100005,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100005,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100005,\"dz\":\"JD\"},\n" +
"{\"docmanId\":100005,\"dz\":\"LT\"},\n" +
"{\"docmanId\":100006,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100006,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100006,\"dz\":\"JD\"},\n" +
"{\"docmanId\":100006,\"dz\":\"LT\"},\n" +
"{\"docmanId\":100007,\"dz\":\"CR\"},\n" +
"{\"docmanId\":100007,\"dz\":\"EU\"},\n" +
"{\"docmanId\":100007,\"dz\":\"JD\"}]";
ObjectMapper objectMapper = new ObjectMapper();
DocmanList docmanList = objectMapper.readValue(json, DocmanList.class);
//logic below
}
public class Docman {
private long docmanId;
private String dz;
public long getDocmanId() {
return docmanId;
}
public void setDocmanId(long docmanId) {
this.docmanId = docmanId;
}
public String getDz() {
return dz;
}
public void setDz(String dz) {
this.dz = dz;
}
}
public class DocmanList extends ArrayList<Docman> {
}
you can do it by generating a class convert it in java object of list.
first generate a class
-----------------------------------com.example.Example.java-----------------------------------
package com.example;
import java.io.Serializable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
public class Example implements Serializable
{
#SerializedName("docmanId")
#Expose
private long docmanId;
#SerializedName("dz")
#Expose
private String dz;
private final static long serialVersionUID = 3195470113916852896L;
/**
* No args constructor for use in serialization
*
*/
public Example() {
}
/**
*
* #param docmanId
* #param dz
*/
public Example(long docmanId, String dz) {
super();
this.docmanId = docmanId;
this.dz = dz;
}
public long getDocmanId() {
return docmanId;
}
public void setDocmanId(long docmanId) {
this.docmanId = docmanId;
}
public Example withDocmanId(long docmanId) {
this.docmanId = docmanId;
return this;
}
public String getDz() {
return dz;
}
public void setDz(String dz) {
this.dz = dz;
}
public Example withDz(String dz) {
this.dz = dz;
return this;
}
#Override
public String toString() {
return new ToStringBuilder(this).append("docmanId", docmanId).append("dz", dz).toString();
}
#Override
public int hashCode() {
return new HashCodeBuilder().append(docmanId).append(dz).toHashCode();
}
#Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Example) == false) {
return false;
}
Example rhs = ((Example) other);
return new EqualsBuilder().append(docmanId, rhs.docmanId).append(dz, rhs.dz).isEquals();
}
}
Now Tell it to parse a List (of Welcome) instead. Since List is generic you will typically use a **TypeReference**
List<Welcome> participantJsonList = mapper.readValue(jsonString, new TypeReference<List<Welcome>>(){});
use http://www.jsonschema2pojo.org/ to convert your json to java class.
You could parse it using JsonPath :
static String json = "...";
public static void main(String[] args) {
String pageName = JsonPath.read(json, "$.pageInfo.pageName");
System.out.println(pageName);
Integer posts = JsonPath.read(json, "$.posts.length()");
for(int i=0; i < posts; i++) {
String post_id = JsonPath.read(json, "$.posts[" + i + "].post_id");
System.out.println(post_id);
}
}

Iterate ArrayList

I want to know the best way to iterate this ArrayList, this ArrayList comes from a Response from an API, this is the ArrayList:
The problem is that i dont know how to get the "id" and the "value" from the loop,
i know the arraylist size but i dont have any idea how to print the "Keys" and "Values" from this Array
for(int i=1; i <= contacts.size(); i++) {
//Example System.out.print(contacts[i]->id);
//Example System.out.print(contacts[i]->contact_name) ;
//Example System.out.print(contacts[i]->numbers);
//Example System.out.print(contacts[i]->emails);
//I want to print id and value
//
}
In onResponse i call this fucntion for example:
ServerResponse resp = response.body();
functionExample((ArrayList) resp.getResponse());
The functionExample have an ArrayList as parameter.
This is my result from my resp.getResponse():
This is my json from the API:
{
"result": "success",
"message": "Lista de Contactos",
"response": [
{
"id": 1,
"contact_name": "EDIFICADORA JUANA",
"numbers": "{24602254,55655545}",
"emails": "{oipoa#gmaio.com,rst008#guan.com}"
},
{
"id": 2,
"contact_name": "LA MEJOR",
"numbers": "{25445877,25845877}",
"emails": "{AMEJOR#GMAIL.COM}"
}
]
}
I appreciate any help.
public void FunctionExample(ArrayList contacts) {
for(int i=0; i < contacts.size(); i++) {
LinkedTreeMap<String, Object> map = (LinkedTreeMap<String, Object>) contacts.get(i);
map.containsKey("id");
String id = (String) map.get("id");
map.containsKey("contact_name");
String contact_name = (String) map.get("contact_name");
map.containsKey("numbers");
String numbers = (String) map.get("numbers");
numbers.replace("{","").replace("}","");
map.containsKey("emails");
String emails = (String) map.get("emails");
emails.replace("{","").replace("}","");
Snackbar.make(getView(), id, Snackbar.LENGTH_LONG).show();
Snackbar.make(getView(), contact_name, Snackbar.LENGTH_LONG).show();
Snackbar.make(getView(), numbers, Snackbar.LENGTH_LONG).show();
Snackbar.make(getView(), emails, Snackbar.LENGTH_LONG).show();
}
}
Try this..It will give arrayList of id's
JSONObject object=new JSONObject(response);
JSONArray array= null;
try {
array = object.getJSONArray("response");
} catch (JSONException e) {
e.printStackTrace();
}
ArrayList<String> idArray=new ArrayList<>();
for(int i=0;i< array.length();i++)
{
idArray.add(getJSONObject(i).getString("id"));
}
Try this way if you are using ArrayList<TreeMap<String, String>> contacts;
for(TreeMap<String,String> contact : contacts){
String id = contact.getValue("id");
}
I would strongly encourage you to use e.g. Jackson to map your JSON response to a proper object. Consider following example:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class JacksonTest {
private static final String JSON = "{\n" +
"\"result\": \"success\",\n" +
"\"message\": \"Lista de Contactos\",\n" +
"\"response\": [\n" +
" {\n" +
" \"id\": 1,\n" +
" \"contact_name\": \"EDIFICADORA JUANA\",\n" +
" \"numbers\": \"{24602254,55655545}\",\n" +
" \"emails\": \"{oipoa#gmaio.com,rst008#guan.com}\"\n" +
" },\n" +
" {\n" +
" \"id\": 2,\n" +
" \"contact_name\": \"LA MEJOR\",\n" +
" \"numbers\": \"{25445877,25845877}\",\n" +
" \"emails\": \"{AMEJOR#GMAIL.COM}\"\n" +
" }\n" +
" ]\n" +
"}";
#Test
public void testParsingJSONStringWithObjectMapper() throws IOException {
//given:
final ObjectMapper objectMapper = new ObjectMapper();
//when:
final Response response = objectMapper.readValue(JSON, Response.class);
//then:
assert response.getMessage().equals("Lista de Contactos");
//and:
assert response.getResult().equals("success");
//and:
assert response.getResponse().get(0).getId().equals(1);
//and:
assert response.getResponse().get(0).getContactName().equals("EDIFICADORA JUANA");
//and:
assert response.getResponse().get(0).getEmails().equals(Arrays.asList("oipoa#gmaio.com", "rst008#guan.com"));
//and:
assert response.getResponse().get(0).getNumbers().equals(Arrays.asList(24602254, 55655545));
}
static class Response {
private String result;
private String message;
private List<Data> response = new ArrayList<>();
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<Data> getResponse() {
return response;
}
public void setResponse(List<Data> response) {
this.response = response;
}
}
static class Data {
private String id;
#JsonProperty("contact_name")
private String contactName;
private String numbers;
private String emails;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContactName() {
return contactName;
}
public void setContactName(String contactName) {
this.contactName = contactName;
}
public List<Integer> getNumbers() {
return Stream.of(numbers.replaceAll("\\{", "")
.replaceAll("}", "")
.split(","))
.map(Integer::valueOf)
.collect(Collectors.toList());
}
public void setNumbers(String numbers) {
this.numbers = numbers;
}
public List<String> getEmails() {
return Arrays.asList(emails.replaceAll("\\{", "")
.replaceAll("}", "")
.split(","));
}
public void setEmails(String emails) {
this.emails = emails;
}
}
}
In this example I used same JSON response you receive and jackson-core library (http://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core/2.8.9) for mapping String to a POJOs (instead of String you can use InputStream, byte[] etc.). There are two POJOs: Response and Data. Response aggregates a list of Data objects. Additionally, Data's getEmails() and getNumbers() methods parse your input String to a list of expected objects. For example if you call setNumbers("{24602254,55655545}") then getNumbers() will return a list of Integers (you can use any numeric type instead) like [24602254, 55655545].
Other suggestions are also valid, e.g. iterating over collection of TreeMaps or JSONObjects. In this example we limit our focus to deal with Java objects with specific types instead of dealing with primitives like Object class for example.
The final solution also depends on your runtime environment. In this case you will have to add jackson-core dependency - it makes more sense if your project already uses Jackson for other reasons.
If you are using Set< Map< String, String>> set;
set.stream().forEach(map -> {
System.out.print("Id:" + map.get("id") + "ContactName:" + map.get("contact_name"));
});
Try this loop to extract every value from ArrayList of yours
List<LinkedTreeMap> list = new ArrayList<LinkedTreeMap>(); //assign result from API to list
for(LinkedTreeMap<String,String> contact : list){
for(String id : contact.keySet()){
if(id.equalsIgnoreCase("id")){
System.out.println("ID: "+ contact.get(id));
}else if(id.equalsIgnoreCase("contact_name")){
System.out.println("Contact Name: "+ contact.get(id));
}else{ //if it is list of numbers or e-mails
String result = contact.get(id);
result = result.replaceAll("{|}", ""); //removing { }
String[] array = result.split(",");
System.out.println(id+": "); // this will be either numbers or e-mails
//now iterating to get each value
for(String s : array){
System.out.println(s);
}
}
}
}

Categories