Converting Json object to hashmap? - java

I have a string object representing a json object returning for a network task. I need to convert it into a Map (or HashMap). I've been using gson, but it has been unsuccessful. Here is the json string (please excuse indentation, for I had to manually add newline spaces):
{
"plans":{
"Ankle Recovery":{
"StartDate":"09/24/2018",
"Progress":0.6666666666666666,
"Tasks":[
{
"date":"10/16/2018",
"amount":200,
"task":"ice ankle for 30 min",
"completed":true,
"requirementType":"steps"},
{
"date":"10/17/2018",
"amount":200,
"task":"ice ankle for 30 min",
"completed":true,
"requirementType":"steps"
},
{
"date":"10/18/2018",
"amount":200,
"task":"ice ankle for 30 min",
"completed":false,
"requirementType":"steps"
}
],
"Username":"email#site.com",
"Doctor":"Mike Michaels",
"EndDate":"12/24/2018"}},
"status":true
}
This is the code I've been using to make the transformation:
private Map<String, String> plans;
plans = new Gson().fromJson(result, new TypeToken<Map<String, String>>() {}.getType());
Neither nor has worked. I've tried some different solutions across Stack Overflow, but none yield success to this point.
I'm also getting an exception thrown that I don't quite understand:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 11
(Column 11 is just before the first quote in "AnkleRecovery")
I'd like to use simple gson to make this work if possible. But I'm open to alternative solutions.

The JSON you posted is not valid, line 3:
"Ankle Recovery" : {
// / \
// this is what you are missing
This tool will help you verify the JSON structure and format it as well: https://jsonlint.com/
Now to the actual problem. Your JSON has a following structure:
{
"plans": Object,
"status": Boolean,
}
Neither of these are strings ( object != string, boolean != string ).
Such a structure can not be mapped to Map<String, String> as this requires the value to be a string.
You will need to create multiple POJOs to define your structure and then map to these, e.g.:
class Project {
public Map<String,Plan> plans;
public Boolean status;
}
class Plan {
public String StartDate;
public Double Progress;
public List<Task> tasks;
...
}
class Task {
...
}

Disclaimer...
I would always investigate using one or more POJOs which can be used to represent the data structure if at all possible.
Without more information, it's impossible to know if keys like Ankle Recovery are stable or not, or if they might change.
"A" possible solution
Generally, JSON is in the form of key/value pairs, where the value might be another JSON object, array or list of other values, so you "could" process the structure directly, for example...
String text = "{\n"
+ " \"plans\":{\n"
+ " \"Ankle Recovery\":{\n"
+ " \"StartDate\":\"09/24/2018\",\n"
+ " \"Progress\":0.6666666666666666,\n"
+ " \"Tasks\":[\n"
+ " {\n"
+ " \"date\":\"10/16/2018\",\n"
+ " \"amount\":200,\n"
+ " \"task\":\"ice ankle for 30 min\",\n"
+ " \"completed\":true,\n"
+ " \"requirementType\":\"steps\"\n"
+ " },\n"
+ " {\n"
+ " \"date\":\"10/17/2018\",\n"
+ " \"amount\":200,\n"
+ " \"task\":\"ice ankle for 30 min\",\n"
+ " \"completed\":true,\n"
+ " \"requirementType\":\"steps\"\n"
+ " },\n"
+ " {\n"
+ " \"date\":\"10/18/2018\",\n"
+ " \"amount\":200,\n"
+ " \"task\":\"ice ankle for 30 min\",\n"
+ " \"completed\":false,\n"
+ " \"requirementType\":\"steps\"\n"
+ " }\n"
+ " ],\n"
+ " \"Username\":\"email#site.com\",\n"
+ " \"Doctor\":\"Mike Michaels\",\n"
+ " \"EndDate\":\"12/24/2018\"\n"
+ " }\n"
+ " },\n"
+ " \"status\":true\n"
+ "}";
Gson gson = new Gson();
Map<String, Object> fromJson = gson.fromJson(text, Map.class);
Map<String, Object> plans = (Map<String, Object>) fromJson.get("plans");
Map<String, Object> recovery = (Map<String, Object>) plans.get("Ankle Recovery");
List<Map<String, Object>> tasks = (List<Map<String, Object>>) recovery.get("Tasks");
for (Map<String, Object> taks : tasks) {
for (Map.Entry<String, Object> entry : taks.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
Now, this would get you the output of ...
date = 10/16/2018
amount = 200.0
task = ice ankle for 30 min
completed = true
requirementType = steps
date = 10/17/2018
amount = 200.0
task = ice ankle for 30 min
completed = true
requirementType = steps
date = 10/18/2018
amount = 200.0
task = ice ankle for 30 min
completed = false
requirementType = steps
Having said all that, your own parsing might be a lot more involved, have to inspect if certain keys exist or not and taking appropriate action as required

Related

Retrieve nested Json when some of the keys are random

So in Java, I have this as my json String:
public static void main(String[] args) {
String stringJson = "{\n" +
"nodes: {\n" +
"Random-key-Here: {\n" +
"name: \"PRO-cnt-elastic2-4-i-0a414518a5b67\",\n" +
"transport_address: \"172.18.7.104:9300\",\n" +
"host: \"189.88.7.884\",\n" +
"ip: \"188.88.8.884:8880\",\n" +
"roles: [\n" +
"\"ingest\"\n" +
"],\n" +
"attributes: {\n" +
"zone: \"us-east-1a\"\n" +
"},\n" +
"tasks: {\n" +
"Random-key-Here: {\n" +
"node: \"-2688888mRPYHywWA\",\n" +
"id: 37202060,\n" +
"type: \"transport\",\n" +
"action: \"indices:data/write/reindex\",\n" +
"status: {\n" +
"total: 4869544,\n" +
"updated: 13920,\n" +
"created: 3654080,\n" +
"deleted: 0\n" +
"},\n" +
"description: \"blaaa\",\n" +
"start_time_in_millis: 1596456902705,\n" +
"running_time_in_nanos: 647855785005,\n" +
"cancellable: true,\n" +
"headers: { }\n" +
"}\n" +
"}\n" +
"}\n" +
"}\n" +
"}";
JsonObject jo = new JsonParser().parse(stringJson).getAsJsonObject();
Set s = jo.get("nodes").getAsJsonObject().entrySet().stream().map(e ->
e.getValue().getAsJsonObject().get("tasks").collect(toSet());
}
Important: notice inside the Json some of the Keys are actually a random string that I couldn't know what it is in advance... - so I Wrote them as "Random-key-Here"
In short: My goal is to retrieve the number of this field, "total: 4869544".
Above that's what I've tried. I've managed to have a list that contains one object member of a set, and it's the "Random-key-Here" as the key, and the value is the rest of my nested json.
I thought if I would repeat the same logic as I did to overcome the first "Random-key-Here" thing, like I did with
.entrySet().stream().map(e ->
e.getValue().getAsJsonObject().get("tasks")
then I would get to another level below, so instead of "tasks" I wrote "status"
and I tought then I would be able to get the rest of the nested json which is easier from then on... but instead, nothing is returned when doing that:
jo.get("nodes").getAsJsonObject().entrySet()
.stream()
.map(e -> e.getValue().getAsJsonObject().get("tasks").getAsJsonObject().entrySet()
.stream()
.map(ent-> ent.getValue().getAsJsonObject().get("status").getAsJsonObject().get("total").getAsJsonObject()))
would appreciate any help to get to the nested part I need which is: "total: 4869544".
and keep in mind, I can't simply just use this:
jo.get("nodes").getAsJsonObject().get("Random-key-Here").getAsJsonObject().get("tasks")
.getAsJsonObject().get("Random-key-Here").getAsJsonObject()
.get("status").getAsJsonObject().get("total").getAsInt()
because of "Random-key-Here".
Tnx for the helpers!
Answer to myself: So, on every unknown key that you have, you can use entrySet()
and then loop over it until you get to your desired field member.
so this usage solves the problem and can get you the nested Json even when your key is unknown in advance:
jo.get("nodes").getAsJsonObject().entrySet()
.forEach(node -> node.getValue().getAsJsonObject().get("tasks").getAsJsonObject().entrySet()
.forEach(task -> { int i = task.getValue().getAsJsonObject().get("status").getAsJsonObject().get("total").getAsInt();
System.out.println(i); }))
pls share if someone has a more efficient way to do so

JsonPath expression to find if a key-value pair is not present in a set of JSON objects?

Given the following JSON:
{
"full_report": {
"score": "5",
"history": {
"record": [
{
"name": "John Smith",
"SSN": "123456789",
"last_visit": "02.03.2019",
"expiry_date": "15.03.2019"
},
{
"name": "John Doe",
"SSN": "987654321",
"last_visit": "05.03.2019",
"expiry_date": "15.09.2019"
},
{
"name": "Jane Doe",
"SSN": "999999999",
"last_visit": "02.03.2019"
}
]
}
}
}
I would like to be able to use JsonPath to find if any of the objects under the record array are missing the expiry_date key and value pair. I currently have a working solution using a method that adds all entries of record to one list and all entries of expiry_date to another and simply checks if the subtraction of both list sizes equals 0 to return a boolean value.
public Boolean isMissing(String json, String expression) {
String[] expr = expression.split(";");
List<String> totalRecords = JsonPath.read(json, expr[0]);
List<String> foundRecords = JsonPath.read(json, expr[1]);
return totalRecords.size() - foundRecords.size() != 0;
}
This requires using two JsonPath expressions with a ; delimiter like so which causes some other, unrelated issues that I'd like to avoid:
$.full_report.history.record[?(#.expiry_date)];$.full_report.history.record[*]
For a copy of this exact structure in XML I can use an XPath expression like so: boolean(full_report/history/record[not(expiry_date/text())])
Any chance there's an equivalent filter that I may have missed in JsonPath?
Update
The answer below by Saeed Alizadeh to use predicate does not solve the problem of having to pass in the property to look for in the first place.
It did help make the method and passing in the property a fair bit cleaner as there's no longer a need to write two separate expressions rather than expression;property_to_lookup. As seen in the method below, that fundamental issue still remains but is much more hassle-free:
public Boolean isMissing(String json, String expression) {
String[] expressionAndPredicate = expression.split(";");
Predicate missingKeyValue = predicateContext -> {
Object missingKey = predicateContext.item(Map.class).get(expressionAndPredicate[1]);
return missingKey == null || missingKey.toString().length() <= 0;
};
List<String> records = JsonPath.read(json, expressionAndPredicate[0], missingKeyValue);
return records.size() != 0;
}
I don't want to add a 3rd parameter to the method for the property nor split the incoming string to sidestep the issue as it creates some issues when providing the JsonPath expression as input at the endpoint. If no one-line expression exists similar to the XPath example, I'll mark the question as answered by Saeed.
As you can see example below by using predicate you can filter result:
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Predicate;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String json = "{\n" +
" \"full_report\": {\n" +
" \"score\": \"5\",\n" +
" \"history\": {\n" +
" \"record\": [\n" +
" {\n" +
" \"name\": \"John Smith\",\n" +
" \"SSN\": \"123456789\",\n" +
" \"last_visit\": \"02.03.2019\",\n" +
" \"expiry_date\": \"15.03.2019\"\n" +
" },\n" +
" {\n" +
" \"name\": \"John Doe\",\n" +
" \"SSN\": \"987654321\",\n" +
" \"last_visit\": \"05.03.2019\",\n" +
" \"expiry_date\": \"15.09.2019\"\n" +
" },\n" +
" {\n" +
" \"name\": \"Jane Doe\",\n" +
" \"SSN\": \"999999999\",\n" +
" \"last_visit\": \"02.03.2019\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
"}";
Predicate expiry_date = new Predicate() {
public boolean apply(PredicateContext predicateContext) {
Object expiry_date = predicateContext.item(Map.class).get("expiry_date");
return expiry_date != null && expiry_date.toString().length() > 0 ? false : true;
}
};
List records = JsonPath.parse(json).read("full_report.history.record[?]", List.class, expiry_date);
System.out.println(records);
}
}
this will print following output as the only record missing "expiry_date" property
[{"name":"Jane Doe","SSN":"999999999","last_visit":"02.03.2019"}]
update
public static boolean isMissing(String json, final String jsonProperty) {
Predicate predicate = new Predicate() {
public boolean apply(PredicateContext predicateContext) {
Object propertyObject = predicateContext.item(Map.class).get(jsonProperty);
return propertyObject != null && propertyObject.toString().length() > 0 ? false : true;
}
};
List records = JsonPath.parse(json).read("full_report.history.record[?]", List.class, predicate);
return (records != null && records.size() > 0) ? true : false;
}
output:
System.out.println(isMissing(json, "expiry_date")); // prints true
System.out.println(isMissing(json, "name")); // prints false

Using Java API TransmissionWithRecipientArray object, how can I set an element like a key value array ( Sparkpost )

I'm sending emails using the Java API TransmissionWithRecipientArray object against a template. I'm facing some problems with the substitution data. I have test this data in the template editor but I don't know how to introduce that substitution data using TransmissionWithRecipientArray.
Here is a sample:
(...), "offers": [
{
"description": "dddddddddddddddddd.",
"discount": "ddddddd",
"image": "ddddddddddddddddddddd",
"image_announcer": "dddddddddddddddddddddddddddd",
"alt_title": "dddddddddddddddddddddd",
"tracking": "dhsdjkhsdjksdh",
"name": "sdhsdohdsiosd",
"id": "8480515",
"announcer_paid": "0",
"announcer_image": "test",
"announcer_alt_title": "wdiohdiowdhiowd"
},
{
"description": "dddddddddddddddddd.",
"discount": "ddddddd",
"image": "ddddddddddddddddddddd",
"image_announcer": "dddddddddddddddddddddddddddd",
"alt_title": "dddddddddddddddddddddd",
"tracking": "dhsdjkhsdjksdh",
"name": "sdhsdohdsiosd",
"id": "8480515",
"announcer_paid": "0",
"announcer_image": "test",
"announcer_alt_title": "wdiohdiowdhiowd"
}, (...)
In other words the question is: What should we introduce in the method setSubstitutionData() to get this input as substitution data? We have validated the substitution data using the template editor.
transmission.setSubstitutionData(allSubstitutionData.asJava)
Mandatory HTML:
{{offers[1].description}}
Per documentation, the way you loop through arrays in a template is:
{{ if offers }}
<ul>
{{ each offer }}
<li>Offer title is <b>{{ loop_var.name }}</b></li>
{{ end }}
</ul>
{{ end }}
you need to use the variable loop_var and if you pass an object in the array, that loop_var will be the root of your object. So if you want to print your discount field, you would need to write loop_var.discount.
There are lots of samples for how to do that sort of thing here.
For your specific case, I think you want something like this.
private void sendEmail(String from, String[] recipients) throws SparkPostException {
TransmissionWithRecipientArray transmission = new TransmissionWithRecipientArray();
// Populate Recipients
List<RecipientAttributes> recipientArray = new ArrayList<RecipientAttributes>();
for (String recipient : recipients) {
RecipientAttributes recipientAttribs = new RecipientAttributes();
recipientAttribs.setAddress(new AddressAttributes(recipient));
recipientArray.add(recipientAttribs);
}
transmission.setRecipientArray(recipientArray);
// Populate Substitution Data
Map<String, Object> substitutionData = new HashMap<String, Object>();
substitutionData.put("yourContent", "You can add substitution data too.");
transmission.setSubstitutionData(substitutionData);
// You can use Jackson, GSON or whatever you standard JSON decoding library is to
// Build this structure.
List<Map<String, String>> offers = new ArrayList<Map<String, String>>();
for (int i = 0; i < 2; i++) {
Map<String, String> offer = new HashMap<String, String>();
offer.put("description", "description value " + i);
offer.put("discount", "discount " + i);
offer.put("image", "image " + i);
offer.put("image_announcer", "image_announcer " + i);
offer.put("alt_title", "alt_title " + i);
offer.put("tracking", "tracking " + i);
offer.put("name", "name " + i);
offer.put("id", "id " + i);
offer.put("announcer_paid", "announcer_paid " + i);
offer.put("announcer_image", "announcer_image " + i);
offer.put("announcer_alt_title", "announcer_alt_title " + i);
offers.add(offer);
}
substitutionData.put("offers", offers);
// Populate Email Body
TemplateContentAttributes contentAttributes = new TemplateContentAttributes();
contentAttributes.setFrom(new AddressAttributes(from));
contentAttributes.setSubject("☰ Your subject content here. {{yourContent}}");
contentAttributes.setText("You could do it for text too. See https://www.sparkpost.com/blog/advanced-email-templates/ for an example");
contentAttributes.setHtml(
"<b>Your Data:</b><br>\n"
+ "<table border='1'>\n"
+ " <tr>\n"
+ " <th>description</th>\n"
+ " <th>discount</th>\n"
+ " <th>image</th>\n"
+ " <th>image_announcer</th>\n"
+ " <th>alt_title</th>\n"
+ " <th>tracking</th>\n"
+ " <th>name</th>\n"
+ " <th>id</th>\n"
+ " <th>announcer_paid</th>\n"
+ " <th>announcer_image</th>\n"
+ " <th>announcer_alt_title</th>\n"
+ " </tr>\n"
+ " {{each offers}} \n"
+ " <tr>\n"
+ " <td> {{{offers.description}}} </td>\n"
+ " <td> {{{offers.discount}}} </td>\n"
+ " <td> {{{offers.image}}} </td>\n"
+ " <td> {{{offers.image_announcer}}} </td>\n"
+ " <td> {{{offers.alt_title}}} </td>\n"
+ " <td> {{{offers.tracking}}} </td>\n"
+ " <td> {{{offers.name}}} </td>\n"
+ " <td> {{{offers.id}}} </td>\n"
+ " <td> {{{offers.announcer_paid}}} </td>\n"
+ " <td> {{{offers.announcer_image}}} </td>\n"
+ " <td> {{{offers.announcer_alt_title}}} </td>\n"
+ " </tr>\n"
+ " {{ end }} \n"
+ "</table>\n\n");
transmission.setContentAttributes(contentAttributes);
transmission.setContentAttributes(contentAttributes);
// Send the Email
IRestConnection connection = new RestConnection(this.client, getEndPoint());
Response response = ResourceTransmissions.create(connection, 0, transmission);
logger.debug("Transmission Response: " + response);
This is what the result looks like:
Thank you guys for your answers.
The issue we had here were with the conversion from a Scala Map type to Gson.
The result of processing with the Gson library HashMaps created from Scala Maps is different. Includes extra fields and changes the structure of the JSON.
The solution is this answer for Java users, and for Scala: iterate firstly all Maps converting to Java types like this:
def toJavaConverter(objectLevelSubs: immutable.Map[String, AnyRef]): java.util.LinkedHashMap[String, Object] = {
val output = new java.util.LinkedHashMap[java.lang.String, Object]
objectLevelSubs.foreach {
case (k: String, v: List[Predef.Map[String, AnyRef]]) => output.put(k, v.map(toJavaConverter))
case (k: String, v: Predef.Map[String, AnyRef]) => output.put(k, toJavaConverter(v))
case (k: String, v: AnyRef) => output.put(k, v)
}
output}
And finally converting each element like this.
val gson: Gson = new GsonBuilder().setPrettyPrinting().enableComplexMapKeySerialization().create()
val finalSubstitutionData: util.LinkedHashMap[String, AnyRef] = new util.LinkedHashMap[String, AnyRef]()
javaObjectLevelSubs.forEach{
case (k: String, v: String) => finalSubstitutionData.put(k, v)
case (k: String, a) => a match {case l: List[_] => finalSubstitutionData.put(k, l.map(gson.toJsonTree).asJava)}
}
Thanks #Yepher and #balexandre

What is the java library to remove/modify a json object based on json path, or how to fix the below issue in JsonPath?

I am trying to implement a function to be able to remove or modify a json object base on a specified json path. For example, if i have a below json string/object:
{
"PersonalDetailsDTO": {
"FirstName": "Mark",
"LastName": "Sully",
"TotalDependent": "2",
"DOB": "19811212",
"SecQuestion": "Some Que",
"SecAnswer": "Some-Ans",
"Mobile": "0123456789",
"Email": "some#validemail.com",
"Title": "Mr",
"EmploymentListDTO": [
{
"Type": "Full-time",
"Probation": true
}
],
"AddressListDTO": [
{
"AddressType": "BUS",
"PostCode": "1234",
"State": "NSW",
"StreetName": "miller",
"StreetNumber": "111",
"StreetType": "Invalid",
"Suburb": "Sydney",
"UnitNumber": "Maximum"
}
]
}
}
And i want to remove element $.PersonalDetailsDTO.AddressListDTO.PostCode.
I've done quite some search, and the one lib i found is JsonPath: http://static.javadoc.io/com.jayway.jsonpath/json-path/2.2.0/com/jayway/jsonpath/JsonPath.html
So i wrote the below code:
public static void main(String[] args) {
// Prints "Hello, World" to the terminal window.
String jsonString = "{\n" +
" \"PersonalDetailsDTO\": {\n" +
" \"FirstName\":\"Mark\",\n" +
" \"LastName\":\"Sully\",\n" +
" \"Title\":\"Mr\",\n" +
" \"DOB\":\"19811201\",\n" +
" \"SecQuestion\":\"Some Ques\",\n" +
" \"SecAnswer\":\"Some-Ans\",\n" +
" \"Email\":\"some#validemail.com\",\n" +
" \"EmploymentListDTO\": [\n" +
" {\n" +
" \"Type\": \"Full-time\",\n" +
" \"Probation\": true\n" +
" }\n" +
" ],\n" +
" \"AddressListDTO\": [\n" +
" {\n" +
" \"AddressType\": \"Residential\",\n" +
" \"PostCode\": \"2345\",\n" +
" \"State\": \"NSW\",\n" +
" \"StreetName\": \"MEL\",\n" +
" \"StreetNumber\": \"2\",\n" +
" \"StreetType\": \"Boulevard\",\n" +
" \"Suburb\": \"Melbourne\",\n" +
" \"UnitNumber\": \"345\"\n" +
" }\n" +
" ]\n" +
" } \n" +
"}";
JSONObject jsonObject = new JSONObject(jsonString);
System.out.println("Before: " + jsonObject.toString());
JsonPath jp = JsonPath.compile("$.PersonalDetailsDTO.AddressListDTO[0].PostCode");
Configuration conf = Configuration.defaultConfiguration();
Object json = conf.jsonProvider().parse(jsonString);
System.out.println("After: " + jp.delete(json, conf).toString());
}
And the console log displays:
Before: {"PersonalDetailsDTO":{"EmploymentListDTO":[{"Type":"Full-time","Probation":true}],"SecAnswer":"Some-Ans","Email":"some#validemail.com","SecQuestion":"Some Ques","FirstName":"Mark","DOB":"19811201","AddressListDTO":[{"StreetName":"MEL","Suburb":"Melbourne","State":"NSW","StreetNumber":"2","UnitNumber":"345","AddressType":"Residential","PostCode":"2345","StreetType":"Boulevard"}],"Title":"Mr","LastName":"Sully"}}
After: {PersonalDetailsDTO={FirstName=Mark, LastName=Sully, Title=Mr, DOB=19811201, SecQuestion=Some Ques, SecAnswer=Some-Ans, Email=some#validemail.com, EmploymentListDTO=[{"Type":"Full-time","Probation":true}], AddressListDTO=[{"AddressType":"Residential","State":"NSW","StreetName":"MEL","StreetNumber":"2","StreetType":"Boulevard","Suburb":"Melbourne","UnitNumber":"345"}]}}
Looks like JsonPath is doing it's job and removing $.PersonalDetailsDTO.AddressListDTO.PostCode. However, there's something very obvious that bothers me:
Looking at the json string produced by .toString() in before and after case, JSONObject API printed a nice string in true json standard format with every double quotes "" present, while the JsonPath .toString produce a customer string format that has some elements in double quote "" while others are not and i can not use it further like JSONObject.
And what i noticed is that although JsonPath claim to accept "java.lang.Object" as parameter in many of its function, what it truely accept is something called "jsonProvider". Not sure if it's causing the weird .toString() behavior.
Anyway, does anyone know how get a nice formatted json string out of JsonPath APIs like remove(), put(), read() and many other? Or to convert the return value to something like JSONObject?
If you know any other Java lib that can do remove/modify element by json path, please feel free to recommand. Thank you!
I don't know JsonPath.
I think you should use jackson which is defacto standard lib when work with JSON in java
aproximate what you are going to do is:
String jsonString = "{"k1": {"k2":"v2"}";
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonString);
actualObj.at("/k1/k2").getValueAsInt()
and replace getValueAsInt with any other function

JAVA - is it possible to filter the sub elements of JSON Object that is large & recursive ??

I want some help to find a quick solution for my problem. Given a json object that is large with a recursive model. I want to list the JSON sub elements & its immediate parent Object( only the sub object which satisfies the given key value condition).
Ex :
{
Object : {
id : "0001",
parent:"A",
child: {
id:"0001A",
Country:"US",
parent:"B",
child:{
id:"0001AA",
Country:"UK",
parent:"C",
child:{
id:"0000AAA",
Country:"US",
parent:"D",
child:{
.........
}
}
}
}
}
}
I want to list the id's of the subObject whose country is 'US' and it's parent id..
is there available any readymade plugins to handle these kind of scenarios in JAVA , without using object mappers/custom class objects..
Ps provide any possible idea ..
Yes, it is possible write code using the Jackson Tree Model API which would traverse a JSON tree and select the nodes that satisfy criteria. Here is an example:
public class JacksonTree2 {
public static final String JSON = "{\"Ex\" : {\"Object\" : {\n" +
" \"id\" : \"0001\",\n" +
" \"parent\":\"A\",\n" +
" \"child\": {\n" +
" \"id\":\"0001A\",\n" +
" \"Country\":\"US\",\n" +
" \"parent\":\"B\",\n" +
" \"child\":{\n" +
" \"id\":\"0001AA\",\n" +
" \"Country\":\"UK\",\n" +
" \"parent\":\"C\",\n" +
" \"child\":{\n" +
" \"id\":\"0000AAA\",\n" +
" \"Country\":\"US\",\n" +
" \"parent\":\"D\",\n" +
" \"child\":{\n" +
" \n" +
" }\n" +
" }\n" +
" }\n" +
"\t}\n" +
"}}}";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(JSON);
for (JsonNode node : root.findParents("Country")) {
if ("UK".equals(node.get("Country").asText())) {
System.out.println(node.get("id"));
break;
}
}
}
}
Output:
"0001AA"

Categories

Resources