Parsing Nested JSON in java without know structure of JSON - java

I have a use case where i get a random jsonstring and variable name. I need to verify if that particular variable is present in that json, and if present fetch its value. For example, let us the json is as follows
{
"a" : {
"b":1,
"c":2
}
}
Along with above jsonString, say i get an input "a.b" . Now I need to return 1.
Is there any library to achieve this in java directly?

JsonPath is a library that provides the functionality you're after.
You will have to do some conversion between your input and the library's input.
As per your example, if your input is "a.b":
String convertedInput = ".." + input
JsonPath.read(json, convertedInput)

Related

Is it a way to configure Jackson ObjectMapper to allow True/False instead true/false?

I have a malformed JSON with "key":True instead of "key":true
So I'm getting the following error :
"com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'True': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')"
I can solve my problem with replace("True", "true") on string before to parsing the JSON string.
But I would like to do this automatically with handling error or something like that. Using Jackson config. Is it possible?
private static final ObjectMapper jsonMapper;
JsonFactory f = JsonFactory.builder()
.enable(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS)
.enable(JsonReadFeature.ALLOW_SINGLE_QUOTES)
.build();
jsonMapper = JsonMapper.builder(f).build();
JsonNode res = jsonMapper.readTree(content)
JSON-sample:
{
...,
"key" : True,
...
}
What you want is inherently impossible.
The parser needs to be able to distinguish between the tokens in order to know how to deal with the next portion of JSON because different JSON-elements should be treated in a different way.
There are only two valid non-String (not enclosed in quotations marks) boolean values: true and false (and null also would be successfully parsed as false). And parsing algorithm depends on them, because it needs to be able to recognize the tokens.
boolean values represented as String, i.e. enclosed in quotations marks, are parsed in the case-insensitive manner automatically without any customization. And for non-String boolean values no formatting features which allow to tweak the behavior of the parser exist.
I'm afraid that there's no other way to solve the problem other then preprocess the JSON adjusting boolean values.
It seems you already know the answer.
You have malformed JSON, and malformed JSON IS NOT JSON.
Jackson ObjectMapper is a JSON processor.
If you want to know more detailed specification and implementation, please refer to the link below:
https://www.json.org/json-en.html
https://github.com/FasterXML/jackson-core/blob/jackson-core-2.14.1/src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java#L741

Best way to parse JSON with an unknown structure for comparison with a known structure?

I have a YAML file which I convert to JSON, and then to a Java object using GSON. This will be used as the standard definition which I will compare other YAML files against. The YAML files which I will be validating should contain fields with identical structures to my definition. However, it is very possible that it might contain fields with different structure, and fields that don't exist within my definition, as it is ultimately up to the user to create these fields before I receive the file. A field in the YAML to be validated can look like this, with the option of as many levels of nesting as the user wishes to define.
LBU:
type: nodes.Compute
properties:
name: LBU
description: LBU
configurable_properties:
test: {"additional_configurable_properties":{"aaa":"1"}}
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 4
capabilities:
virtual_compute:
properties:
virtual_memory:
virtual_mem_size: 8096 MB
virtual_cpu:
cpu_architecture: x86
num_virtual_cpu: 2
virtual_cpu_clock: 1800 MHz
requirements:
- virtual_storage:
capability: capabilities.VirtualStorage
node: LBU_Storage
Currently, I receive this YAML file and convert it to a JsonObject with Gson. It is not possible to map this to a Java object because of any possible unknown fields. My goal is to run through this file and validate every single field against a matching one in my definition. If a field is present that does not exist in the definition, or does exist but has properties that differ, I need to inform the user with specific info about the field.
So far, I am going the route of getting fields like this.
for (String field : obj.get("topology_template").getAsJsonObject().get("node_template").getAsJsonObject().get(key).getAsJsonObject().get(
obj.get("topology_template").getAsJsonObject().get("node_templates").getAsJsonObject().get(key).getAsJsonObject().keySet().toArray()[i].toString()).getAsJsonObject().keySet()) {
However, it seems that this is rather excessive and is very hard to follow for some deeply nested fields.
What I want to know is if there is a simpler way to traverse every field of a JsonObject, without mapping it to a Java object, and without explicitly accessing each field by name?
I think you are looking for something like a streaming Json Parser:
Here's an example
String json
= "{\"name\":\"Tom\",\"age\":25,\"address\":[\"Poland\",\"5th avenue\"]}";
JsonFactory jfactory = new JsonFactory();
JsonParser jParser = jfactory.createParser(json);
String parsedName = null;
Integer parsedAge = null;
List<String> addresses = new LinkedList<>();
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
if ("name".equals(fieldname)) {
jParser.nextToken();
parsedName = jParser.getText();
}
if ("age".equals(fieldname)) {
jParser.nextToken();
parsedAge = jParser.getIntValue();
}
if ("address".equals(fieldname)) {
jParser.nextToken();
while (jParser.nextToken() != JsonToken.END_ARRAY) {
addresses.add(jParser.getText());
}
}
}
jParser.close();
Please find the documentation here:
https://github.com/FasterXML/jackson-docs/wiki/JacksonStreamingApi

Read a Java array in Javascript

I've a method that returns a 2d-array in java : public Object[][] getArray1() {}
I used println() to print it's content and i see that its well created.
On Javascript i assign this array to a var:
var content ="#{BDEStats.getArray1()}";
But i dont seem able to acess it's data. it always returns java.Lang.object; #... How can i do to display the content this array holds?
I've tried to cycle the array but i dont know how to refer to the objects it is holding. if i use content[1] to returns a char in that índex..! Kinda lost here
I think you may convert the array to JSON format before assigning it to javascript.
You can use some JSON framework to do this convert like:
JSON-lib
Jackson
Here a tiny Jackson demo:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
...
public static void main(String[] args) throws JsonProcessingException {
String[][] data = new String[1][2];
data[0][0] = "abc";
data[0][1] = "def";
System.out.println(new ObjectMapper().writeValueAsString(data));
}
This is the normal array String representation in Java, consisting in:
A number of [ based on the dimension
Either a letter for the primitive type (i.e. I for int), or L[fully qualified class name] for Objects
#
The array's hash code
For one-dimensional arrays, use java.util.Arrays.toString(myArray).
For multi-dimensional arrays, use java.util.Arrays.deepToString(myArray).
Edit (adding previous comment to answer)
You probably want to investigate JSON.parse to parse your Java array from JavaScript.
To turn a Java array into a string representation in a syntax which can be interpreted by a JavaScript engine, you need to turn it into the JavaScript Object Notation, or JSON for short.
There are many libraries available for Java to do this. Software recommendations are off-topic on Stackoverflow, but this article which compares 5 different libraries helped me to pick one for my project.
On the JavaScript side, you just have to use var content = JSON.parse(stringFromJava).
Or when you generate the JS code procedurally on the Java side, you can just embed the JSON string right into the sourcecode. This works because JSON is valid Javascript code for an object literal. In Java, this would look something like this:
scriptCode.append("var content = " + arrayAsJsonString + ";\n");
Ok problem solved. This was how I did it:
Instead of returning a Java Array I returned a JSON object in my method.
This JSON Object has a name and several other fields per ex:
(I'm getting my data from a Java List, so I iterate the list to populate the JSON object)
SONObject jsonObj = new JSONObject();
jsonObj.clear();
for (int tt=0; tamanho>tt ; tt++) {
try {
jsonObj.put("aa"+tt, ListaJobStats.get(tt).getName());
jsonObj.put("bb"+tt , new BigDecimal(ListaJobStats.get(tt).getAge() ....
After this if I printOut the JSON object in java i get a string:
aa0: '1st name'; aa1: ' 2nd name' ; bb0: 'age'; bb1: '2nd age' ... etc etc
After this in Javascript i get my JSON Object thorugh JSF like this:
var content=#{JAVACLASS.METHODTHATRETURNSJSON};
I stringify this object in JS:
var pars= JSON.stringify(content);
and i create the JSON object
var json = JSON.parse(pars)
Now I Iterate this JSON object in JS like this:
for (var tt=0; tamanho>tt ; tt++) {
[now im specifically adding the values to create a graphic but its just na exemple how u can acess te object]
data.setValue(tt, 0, json["aa"+tt]);
data.setValue(tt, 1, json["bb"+tt]);
...
Hope it will be useful. Take care

Java parsing JSON in args

Can you anyone help me with problem of parsing args in java?
I need to read JSON data by args in two formats(file, text arg). If an arg is path to file with JSON text, it's working.
In main method I'm reading args:
public static void main(String[] args){
String argText = args[1]
}
But if I'm put to arg some JSON text (for example: {"server1":{"dname":"www.server.com","lat":"40","lng":"17"}) it's problem with quotes, because in
String argText is stored text without quotes:
System.out.println("Text: " + argText);
Text: {server1:{dname:www.server.com,lat:40,lng:17}
And method for parsing JSON:
public static JSONObject parseJSON(String argText){
if (text.contains("{")){
//arg is text and I want to store it as JSONObject
// how to store text with "
} else {
//argText is file....
// read file, put in new JSONObject
// it works without any problems.
}
return JsonObject
}
I don't know it is the good way to read input args, but for file it's working and I would to add reading form the text.
If argText contains escaped quotes \\\" everythig is OK, but I don't have text in these format.
EDIT:
So I don't have problem with parsing JSON bud I need some method that doing:
public static void(String quotedText){
//do something...
System.out.print("Output: " + text);
}
with in/out:
< '"text":"val1","val2","val3"'
Output: "text":"val1","val2","val3"
In Win system.out.print is:
'Output: text:val1,val2,val3'
The quotes are munged by the shell; put the whole string in single quotes for that to work. If your utility is launched by some other program, fix that program to escape everything, or transport it using stdin.
If using library does not suit your needs, you can make a simple method to covert it.
Add " after every {, before every }, and both before and after every , and :.
There might be some ambiguity with those chars, but that why quotes are supposed to be there at first place.
Maybe you should use some standard library for parsing JSON, it will really save you a lot of time. JSON isn't that simple that you can just treat it like a simple string.
Try:
http://jackson.codehaus.org/
https://code.google.com/p/json-simple/
You should try a standard library to parse JSON, like Alexander said.
There are some out there that convert JSON into Java objects. I personally like XStream. Try this JSON with Xtream tutorial
With it, you can define your own Java objects and use the library to convert JSON to those objects and from the objects to JSON. No need to create your own parser.
I recommend this simple and widely used library: GSON

How to create a JSONArray that contains Javascript code inside Java?

I am creating a JSONArray and parse it to a String, but as it even contains Strings instead of code it doesn't output as I need it.
for(Place place: places){
locations.put("new google.maps.LatLng("+place.getContactData().getLatitude()+","+place.getContactData().getLongitude()+")");
}
return locations.toString();
It outputs as: ["new google.maps.LatLng(53.5608,9.96357)","new google.maps.LatLng(53.5608,9.96357)"] but I need it without quotation marks like [new google.maps.LatLng(53.5608,9.96357),new google.maps.LatLng(53.5608,9.96357)] to be correctly interpreted by javascript.
Another method would be:
create an array with just the coordinates:
for(Place place: places){
JSONObject obj = new JSONObject();
obj.put("lat",place.getContactData().getLatitude());
obj.put("lng",place.getContactData().getLongitude());
locations.put(obj);
}
and then in javascript:
var places = (yourPlacesJson);
var placeObjects = [];
for(var i=0;i<places.length;i++)
{
placeObjects[placeObjects.length] = new google.maps.LatLng(places[i].lat,places[i].lng);
}
JSON only supports plain-old-data. It can't include any executable code (a new is executable code). This is by design - when JSON would be able to include executable code you would have to be much more carefully with importing JSON from an untrusted source.
All you can do is pass javascript code as strings and eval() it on the JS side after parsing the JSON.
Also you could use Regular expressions to remove the ", if you parse the json to another language
i had a similar problem, the way i made this work:
instead of writing the javascript before the json conversion, insert a placeholder.
locations.put("%mapsPlaceholder1%");
then after filling the array with placeholders, do:
locations.toString().replaceFirst("\"%mapsPlaceholder1%\"","yourJsCode");
something like that
you could also just create the array string manually

Categories