Parsing this JSON with Java? - java

When Parsing JSON I normally just constuct an object and use the gsonlibrary to parse my String into that object.
However, I now find myself with a rather complex response which consists of many elements each with sub elements of objects and arrays and arrays of objects. It looks something like this...
{
"type": "thetype",
"object":{
"text": "texthere",
"moretext": "more here"
},
...,
...,
...,
...,
"fieldIwant": [
{
"object":"object!"
},
....
....
{
"object":"object!"
},
]
}
The thing is, I'm only really interested in fieldIwantand nothing else. Is there not a way in Java for me to just extract that field and work with it alone and not all this other dead weight I do not need?

According to this http://sites.google.com/site/gson/gson-design-document it looks like gson does this for you by default.
When you are deserializing a Json string into an object of desired type, you can either navigate the tree of the input, or the type tree of the desired type. Gson uses the latter approach of navigating the type of the target object. This keeps you in tight control of instantiating only the type of objects that you are expecting (essentially validating the input against the expected "schema"). By doing this, you also ignore any extra fields that the Json input has but were not expected.
In other words, it doesn't deserialize any of the fields you don't need. You should be good to go.

You can use the low level JsonParser API
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
yourArray = new Gson().fromJson(jsonObject.get("fieldIwant"), yourArrayType);
Alternatively you can create an ExclusionStrategy to use with a GsonBuilder

Related

FreeMarker template error: JSONArray wrapped into f.e.b.StringModel

i'm trying to send JSON object to my free marker, but i getting error while testing JUnit
here is my object
{
"filename": "test",
"orderId": "123435",
"orderDate": "23.09.2020г.",
"itemsCount": "4",
"items": [
{
"itemName": "ТВ Приставка 400",
"itemCount": "2 шт Х 400₽",
"itemSum": "800.00"
}
],
"totalSumm": "3000.00"
}
here is my error:
FreeMarker template error:
The value you try to list is an extended_hash+string (org.camunda.bpm.engine.impl.util.json.JSONArray wrapped into f.e.b.StringModel), thus you must specify two loop variables after the "as"; one for the key, and another for the value, like <#... as k, v>).
how could i resolve it?
items is a arrays of JSON objects
FreeMarker knows nothing about org.camunda.bpm.engine.impl.util.json.JSONArray, so it doesn't see it as a list-like thing (as a sequence, as it's called in FTL). So you can do one of these:
Using the objectWrapper Configuration setting, you teach FreeMarker how to treat JSONArray as a list. (You can find more about custom ObjectWrapper-s elsewhere.) Then you can just #list such objects, and use all the other operations applicable to sequences.
Or, you call the Java API-s of JSONArray from the template. That will be less convenient of course, but requires no prior investment.

Parsing a subset of JSON in Java using Jackson

Given a Json, is it possible to use Jackson to only parse out a section of the message?
Say that the data I'm interested in is buried in a deep hierarchy of fields and I simply do not care about creating DTO classes for each and every class.
Given a very simplified scenario I'd like to model the Telephone class without knowing anything about the structure before it:
...{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
},
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888"
},
{
"type" : "home",
"number": "0123-4567-8910"
}
]
}....
I'm thinking something in the terms of using json-path together with deserializing just the parts I'm interested of. Some pseudo:
List<Telephone> phoneNrs = parse(".my.deep.structure.persons.phoneNumbers", List<Telephone.class>);
ObjectMapper mapper = new ObjectMapper();
JsonNode json = mapper.readTree("... your JSON ...");
Using the JsonNode object you can then call get("my").get("deep").get("structure") to get the node you want.
Once you got your hands on that node, a simple call to mapper.treeToValue(myDeepJsonNode, Telephone[].class) will get you your array ofTelephone. You can get a list using a TypeReference as well.
To get to your deep JsonNode you can also use the findValue and findPath methods.
The Javadoc:
https://fasterxml.github.io/jackson-databind/javadoc/2.2.0/com/fasterxml/jackson/databind/JsonNode.html
Yes, it is possible the way you have mentioned in the Pseudo code. "phoneNumbers" is a key and value returned can be passed on to Jackson deserialiying.
If the response is an array of maps then you can iterate through each one of them and use the yourResponseAsJSONObject.get('phoneNumbers') method to get the value and pass it on to Jackson
or use JsonPath as mentioned by #dimas
You can use JsonPath library. With this library you can map your JsonPath output directly into POJO's.
Pseudo:
List<Telephone> phoneNrs = JsonPath.parse(json).read("$.my.deep.structure.persons.phoneNumbers", List.class);
To do this efficiently with Jackson, use the Streaming API via the JsonParser class (http://fasterxml.github.io/jackson-core/javadoc/2.5/com/fasterxml/jackson/core/JsonParser.html).
This approach will allocate no additional memory and will not incur the cost of deserializing values for all of the skipped data. Since the code will be much longer and more difficult to read than using Jackson's ObjectMapper, only do this if profiling shows unacceptable GC activity or CPU usage during parsing.
You can skip all of the nodes that you are uninterested in until you hit the "phoneNumbers" key. Then you can call the readValueAs function to deserialize the array of phone number dictionaries like so readValueAs(new TypeReference<MyPhoneNumberType[]>()).
See also:
a tutorial on reading and writing with JsonParser: http://www.cowtowncoder.com/blog/archives/2009/01/entry_132.html
The main documentation: https://github.com/FasterXML/jackson-core

I need to transform a JsonObject into a hashmap, but the structure of the JSON is a bit different

This is the structure of the JSON that I need to transform:
{
"United Kingdom": {
"visit_count": 2,
"cities": {
"London": 2
}
},
"Netherlands": {
"visit_count": 1182,
"cities": {
"Amsterdam": 441
}
}
}
Which is basically a JSonObject, which contains an array of objects, BUT the key is the name of the country, and the right part, are the properties of the object. The same goes for the "Cities" JsonObject.
Now I tried doing this with jsonschema2pojo, but it tries to create objects after the name of the countries (United Kingdom, Netherlads) when this objects are actually the same type.
I was thinking of somehow loading the json into a hashmap, but don't know how exactly to do that. Is is possible?
Use google's Gson, it works excellent.
https://code.google.com/p/google-gson/
And take a look into here
You can try to use JSON-simple library: https://code.google.com/p/json-simple/
JSONObjects parsed by this library are literally represented as a HashMap. (org.json.simple.JSONObject extends HashMap) :-)

How to transform string with objects and array indexes into json

I receive from another program Map with string representation of elements:
Map<String,String> properties = new HashMap<String,String>() {{
put("news[0].title", "Title 1");
put("news[0].body", "Body 1");
put("news[1].title", "Title 2");
put("news[1].body", "Body 2");
}};
I need to render it into freemarker-template. In question
freemarker-flat-structure-of-passing-parameters-transfer-to-array-of-objects
we decided that it is impossible to parse this kind of values in freemarker. But freemarker can eval json.
So I need to know how to transform this map into objects or json. I need something like that:
{
"news": [
{"title": "Title1", "body": "Body1"},
{"title": "Title2", "body": "Body2"}
]
}
Names of parameters in map are unknown, not exactly "news", not exactly "title" and "body", I don't know.
May be there are some libraries for such purposes?
Since you are using your own language there, just write a parser for it. It's not a complex language after all. Also, transforming it to JSON doesn't make sense, based on what I know about the problem. Yes, the FTL expression syntax and JSON syntax overlaps quite much. But you shouldn't parse anything inside the FTL-s, just parse your language to List-s and JavaBeans and/or Map-s, and pass that plain Java object to FreeMarker.
GSon and Jackson libraries are there for conversion between Java objects and JSON strings.

JSON Parsing problem

Hey,
Im trying to parse the following JSON data:
{"chat":
{"link":
[{"#rel":"next","#ref":"http"}],
"events":
{"link2":
[{"#rel":"next","#ref":"http"}]}
}}
The code that reads the data is (where 'a' is the JSON as String):
JSONObject jsonObject1 = new JSONObject(a);
JSONObject jsonObject = jsonObject1.getJSONObject("chat");
So the structure (at least the way I intended) is:
<chat>
<link>
<events>
<link2>
</events>
</chat<
But, after getJsonObject("chat"), jsonObject equals to:
{"chat":{"events":{"link2":[{"#ref":"http","#rel":"next"}]},"link":[{"#ref":"http","#rel":"next"}]}}
What am I missing? Why does the data flips and the structure changes?
The properties in a JSON object are not sorted. From the JSON site:
An object is an unordered set of name/value pairs...
(My emphasis) Therefore the position of link and event are irrelevant for the parser. Bottom line, link and event are at the same level therefore they can be shifted and wherever order matters use arrays in JSON ... [].

Categories

Resources