Jackson deserialization convertValue vs readValue - java

I have a org.json.JSONArray that contains JSONObjects and I am trying to map those to a POJO. I know the type of the POJO I want to map to. I have 2 options and I m trying to figure out which is better in performance.
Option 1:
ObjectMapper mapper = new ObjectMapper();
ObjectReader reader = mapper.reader().withType(MyPojo.class);
for (int i = 0; i < jsonArr.length(); i++) {
JSONObject obj = jsonArr.getJSONObject(i);
MyPojo pojo = reader.readValue(obj.toString());
... other code dealing with pojo...
}
Option 2:
ObjectReader mapper = new ObjectMapper();
for (int i = 0; i < jsonArr.length(); i++) {
JSONObject obj = jsonArr.getJSONObject(i);
MyPojo pojo = mapper.convertvalue(obj, MyPojo.class);
... other code dealing with pojo...
}
For sake of argument, lets assume the length of the JSONArray is 100.
From what I have looked so far from the source code, option 1 seems better since the Deserialization context and the Deserializer is created only once, while in case of option 2, it will be done for each call.
Thoughts?
Thanks!

I will try to explain the difference, with the problem I faced. I used both in a complex conversion I needed to use.
My request was of the format as below.
"{Key=a1, type=ABC}"
I wanted to convert it to some class's (A1) instance.
class A1 {
private String key;
private String type;
}
As is clear, the keys are not strings (i.e. not enclosed in double quotes)
With mapper.readValue
I will get error as below:
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('k' (code 115)): was expecting double-quote to start field name
With mapper.convertValue
I will get an instance of A1 as I required.

Related

Iterate JSON and get fields from JSON

I've tried different solutions but I'm not able to iterate through this JSON and/or get direct specific values.
Could any one help on:
Iterating through all the fields sequentially.
Getting direct access to some fields (eg. when getting this response, access directly to "packet-count" where its value equals 3281).
{"flow-node-inventory:flow":[{"id":"42","priority":10,"table_id":0,"opendaylight-flow-statistics:flow-statistics":{"packet-count":3281,"byte-count":317738,"duration":{"nanosecond":252000000,"second":3432}},"idle-timeout":10000,"cookie":31,"instructions":{"instruction":[{"order":0,"apply-actions":{"action":[{"order":0,"output-action":{"output-node-connector":"1","max-length":0}}]}}]},"match":{"ethernet-match":{"ethernet-source":{"address":"00:00:00:00:00:02"},"ethernet-destination":{"address":"00:00:00:00:00:01"}}},"hard-timeout":50000,"flags":""}]}
I tried to use org.json but any other library would be okay.
You will have to check the structure of your JSON Object and create a structure for the entities you encounter accordingly. For instance, the first thing in your JSON object is an array, so this is the first thing you should care about. Imagine it as a continuous encapsulation. Check the code below for more information.
JSONObject jobj = new JSONObject(stringJson);
JSONArray flowNodeInv = jobj.getJSONArray("flow-node-inventory:flow");
for (int i = 0; i < flowNodeInv.length(); i++){
JSONObject segment = (JSONObject) flowNodeInv.get(i);
JSONObject stats = segment.getJSONObject("opendaylight-flow-statistics:flow-statistics");
int number = stats.getInt("packet-count");
System.out.println("packet-count: "+ number);}
Try This
jObject = new JSONObject(contents.trim());
Iterator<?> keys = jObject.keys();
while( keys.hasNext() ) {
String key = (String)keys.next();
if ( jObject.get(key) instanceof JSONObject ) {
}
}
To get direct access to the fields you can create a Java Object from the JSON String using an ObjectMappet (com.fasterxml.jackson). For example:
ObjectMapper mapper = new ObjectMapper();
MyClass myClass = mapper.readValue(jsonString, MyClass.class);

Parse nested JSON with varying number of entries

I'm working on a bus transit app and one of the network calls I need to make gets the trip info on how to get from point A to point B. The bus transit API has a method that provides this info. The method returns up to 3 viable itineraries, and each itinerary has a variable amount of legs. There are also two types of legs, walking legs and riding legs.
I was wondering on how I should go about parsing this data and then transferring it to the UI. What's throwing me off is that the nested entries also have nested arrays of variable length (that can be of either two types). To first retrieve the data I think using an ArrayList of ArrayList could work. Should I then create two models that correspond to the two type of legs, add the data to those, and then dynamically add those to the listView I'm going to use to display the results? (I would also have to dynamically add the itineraries).
Oh and another thing. If the bus you need to get on finishes a route and starts a new one (while you need to stay on it the whole time) It will return multiple services in a single leg and I have no idea how to efficiently check for that and convey that to the user.
This is what I have so far (only have code for parsing right now).
final String JSON_ITINERARIES = "itenararies";
final String JSON_STOP_NAME = "stop_name";
final String JSON_STOP_LAT = "stop_lat";
final String JSON_STOP_LONG = "stop_long";
final String JSON_STOP_ID = "stop_id";
try {
JSONArray itinerariesArray;
JSONObject stopsJson = new JSONObject(JsonStr);
itinerariesArray = stopsJson.getJSONArray(JSON_ITINERARIES);
ArrayList itinerariesArrayList = new ArrayList<ArrayList<String>>(itinerariesArray.length());
for (int i = 0; i < itinerariesArray.length(); i++) {
JSONObject singleTrip = itinerariesArray.getJSONObject(i);
JSONArray singleTripLegsJSON = singleTrip.getJSONArray("legs");
ArrayList legsArrayList = new ArrayList<String>(singleTripLegsJSON.length());
for (int j=0; j<singleTripLegsJSON.length(); j++) {
JSONObject SingleTripObjectSingleLeg = singleTripLegsJSON.getJSONObject(j);
String TYPE = SingleTripObjectSingleLeg.getString("type")
//?????
}
I recommand you to use GSON. GSON is very very very useful tool for JSON.
First, use http://www.jsonschema2pojo.org/ to make class from json.
Copy & paste your json string to this site,
select "source type : JSON",
select "Annotation style: GSON",
press "Preview" OR "JAR" to get JAVA classes.
Second, use GSON to parse your json string. Visit Here to get more examples.
example:
private Gson gson = new Gson();
String sampleData = //
"[" //
+ "{\"info\": {\"place\": \"place1\"},"
+ "\"events\": {\"info\": \"555f1fc297f229004dd6e8aa\",\"time\": \"5\",\"image\": \"555f1fc2d197270b6c732d3b\",\"event_name\": \"555f1fc224d1cb629a8ef603\"}},"
+ "{\"info\": {\"place\": \"place3\"},"
+ "\"events\": {\"info\": \"555f1fc283c7b150ede89c05\",\"time\": \"7\",\"image\": \"555f1fc2bf5fa8a3b320e0ca\",\"event_name\": \"555f1fc20d40f1b478610505\"}},"
+ "{\"info\": {\"place\": \"place2\"},"
+ "\"events\": {\"info\": \"555f1fc29163e85ae42e7518\",\"time\": \"6\",\"image\": \"555f1fc21506a186c2d34a92\",\"event_name\": \"555f1fc272a06e68b8c3f4b7\"}}" + " ]";
java.lang.reflect.Type listType = new TypeToken<List<Event>>() {
}.getType();
ArrayList<Event> eventList = gson.fromJson(sampleData, listType);

validate JSON string if the value of parameter is string or an array

this is JSON string 1
{"title":["1","2"], "amount":["1","2"]}
this is JSON string 2
{"title":"", "amount":""}
string 1 is created when I enter values in form and string 2 is created when I dont,
I want to know if the string is in format 1 that is title is an array ["1", "2"] or format 2 that is title is just a string "" on the server side in a servlet, before I parse it. is there any way of doing so?
this is my previous question,
How do I parse this JSON string using GSON in servlet
which is solved but as you can see there i have class Data which has instance variables of type ArrayList, so when I parse it with this line
Data data = gson.fromJson(param, Data.class);
it throws exception
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 24
because as I have declared ArrayList, it expects array only in json to parse it without any exceptions....but when I dont enter values in my form it doesnt create json string as
{"title":[], "amount":[]}
rather it creates like this
{"title":'', "amount":''}
which has string as value, which causes parsing to throw exception
Had this problem as well and this is how I got around it
In your Data object have
public class Data {
// This is a generic object whose type is determined when used by GSON
private Object title;
// get the type of object and return as string
public String getTitleObjType() {
String objType = title.getClass().toString();
return objType;
}
// used if the object is an ArrayList, convert into an ArrayList<Object>
public ArrayList<String> getTitleArrayList() {
// Turn the Object into an arraylist
#SuppressWarnings("unchecked") // This is to counter the fact that the cast is not type safe
ArrayList<String> titleArrayList = (ArrayList<String>) title;
return titleArrayList;
}
// used if the object is not an array
public String getTitleStr() {
return title.toString();
}
}
When GSON builds the object it will create and each of these to be either a String or an ArrayList
Then when you want to use the objects, test to see what they are
ArrayList<String> titleValArrayList = new ArrayList<String>();
String titleValStr = "";
if(getTitleObjType.equals("class java.util.ArrayList")) {
titleValArrayList = getTitleArrayList();
//do whatever you like
}
else if(getTitleObjType.equals("class java.util.String")) {
titleValStr = getsTitleStr();
//do whatever you like
}
Check Google GSON it allows you to parse JSON server side.
It goes something like this:
String jsonString = request.getParameter("jsonParemeter");
Gson gson = new Gson();
Map fromJsonMap = gson.fromJson(jsonString, HashMap.class);
Object object = fromJsonMap.get("title");
if (object instanceof Collection) {
// then is it's your array
}
else {
// it's not
}
If, for example, I run the following example code:
String json1 = "{\"title\":[\"1\",\"2\"], \"amount\":[\"1\",\"2\"]}";
String json2 = "{\"title\":\"\", \"amount\":\"\"}";
Gson gson = new Gson();
HashMap map = gson.fromJson(json1, HashMap.class);
HashMap map2 = gson.fromJson(json2, HashMap.class);
System.out.println(map);
System.out.println(map2);
System.out.println(map.get("amount").getClass());
System.out.println(map2.get("amount").getClass());
I get as output:
{amount=[1, 2], title=[1, 2]}
{amount=, title=}
class java.util.ArrayList
class java.lang.String
If I understood you correctly I think it suits you 100%
UPDATE
Since you are trying to deserialize your JSON string directly to a Data object, if you want to keep doing that direct deserialization you have to use a custom deserialization mechanism

how to get 2 values from a nested Json string with jackson

I m using jackson library to deserialize from Json. I need to extract only 2 value from this json i.e. c1 and d1. I have used this code... I need to know the correct approach to overcome get c1 and d1 values...
My json
{"Alpha":{"A":{"B":{"C":{"c1":1234,c2:"abcd"},"D":{"d1":"xyz","d2":5678,"d3":"qwerty"},"E":[{"e1":456,"e2":"mnop"},{"e1":098,"e2":"qrst"}]}}},"X"{"x1":8098}}
ObjectMapper mapper = new ObjectMapper();
mainclass alphaobj = mapper.readValue(new File("C:\\employee.json"), mainclass.class);
System.out.println(alphaobj.A.B.C.getc1());
Maybe you should use Jackson Tree Model instead?
Something like:
JsonNode root = mapper.readTree(file);
int c1 = root.path("Alpha").path("A").path("C").path("C1").intValue();
and so on.

JSON parsing to Java - Android application

I need help with parsing json string in Java Android Appl.
Text of JSON file:
{"data":{"columns":["location_id","name","description","latitude","longitude","error","type","type_id","icon_media_id","item_qty","hidden","force_view"],"rows":[[2,"Editor","",43.076014654537,-89.399642451567,25,"Npc",1,0,1,"0","0"],[3,"Dow Recruiter","",43.07550842555,-89.399381822662,25,"Npc",2,0,1,"0","0"] [4,"Protestor","",43.074933,-89.400438,25,"Npc",3,0,1,"0","0"],[5,"State Legislator","",43.074868061524,-89.402136196317,25,"Npc",4,0,1,"0","0"],[6,"Marchers Bascom","",43.075296413877,-89.403374183615,25,"Node",22,0,1,"0","0"] [7,"Mary","",43.074997865584,-89.404967573966,25,"Npc",7,0,1,"0","0"]]},"returnCode":0,"returnCodeDescription":null}
How can get values: location_id, name, latitude, longitude.
Thanks, Michal.
Using manual parsing you can implement it like this:
JSONArray pages = new JSONArray(jsonString);
for (int i = 0; i < pages.length(); ++i) {
JSONObject rec = pages.getJSONObject(i);
JSONObject jsonPage =rec.getJSONObject("page");
String address = jsonPage.getString("url");
String name = jsonPage.getString("name");
String status = jsonPage.getString("status");
}
in your case note that your outer elemnt data is type of JSONObject and then you have a JSONArray
mine json file:
[{"page":{"created_at":"2011-07-04T12:01:00Z","id":1,"name":"Unknown Page","ping_at":"2011-07-04T12:06:00Z","status":"up","updated_at":"2011-07-04T12:01:00Z","url":"http://www.iana.org/domains/example/","user_id":2}},{"page":{"created_at":"2011-07-04T12:01:03Z","id":3,"name":"Down Page","ping_at":"2011-07-04T12:06:03Z","status":"up","updated_at":"2011-07-04T12:01:03Z","url":"http://www.iana.org/domains/example/","user_id":2}}]
note that mine starts from [, which means an array, but yours from { and then you have [ array inside. If you run it with a debugger, you can see exactly what´s inside your json objects.
There are also better approaches like:
Jackson
Jackson-JR (light-weight Jackson)
GSON
All of them can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object.
First of all, you need to know about Json parsing in android, so for that first read this: JSONObject, in that class, you will see the below methods:
getJSONArray(String name)
getJSONObject(String name)
getString(String name)
and many more methods to be used while implementing JSON parsing in android.
Update:
And if you are still confused then click on below link to have many examples available on web: Android JSON Parsing
You need to use the GSON lib
http://code.google.com/p/google-gson/
Object Examples
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
(Serialization)
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
==> json is {"value1":1,"value2":"abc"}
Note that you can not serialize objects with circular references since that will result in infinite recursion.
(Deserialization)
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
==> obj2 is just like obj
If you mean to navigate easily the Json Tree, you can use JSON Path, that is query system, similar to XPath to XML, that you can use to pick some elements in a json tree using text expressions.
http://code.google.com/p/json-path/ That's a good implementation
If you just mean that you want to parse that JSon you can use Gson from google (that is compatible with Android I guess).
This contains a complete example for your case.

Categories