How to groupby json value like python in java? - java

I'm new in java but I have some knowledge in python,
I need to transform json value like this:
{'ID':'id1','ref':'ref1','categ':'CATEG_A','pagenb':1},
{'ID':'id2','ref':'ref1','categ':'CATEG_A','pagenb':2,},
{'ID':'id3','ref':'ref1','categ':'CATEG_B','pagenb':3}
To this:
{'ID':['id1','id2],'ref':'ref1','categ':'CATEG_A'},
{'ID':'id3','ref':'ref1','categ':'CATEG_B',},
in python I use pandas dataframe to groupby but I don't find the best way to do this in java
categ value is a variable dynamic, can change

https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(
"[" +
" {\"ID\":\"id1\",\"ref\":\"ref1\",\"categ\":\"CATEG_A\",\"pagenb\":1}," +
" {\"ID\":\"id2\",\"ref\":\"ref1\",\"categ\":\"CATEG_A\",\"pagenb\":2}," +
" {\"ID\":\"id3\",\"ref\":\"ref1\",\"categ\":\"CATEG_B\",\"pagenb\":3}" +
"]");
JsonNode node = josson.getNode("group(map(ref, categ), ID).map(ID, key.ref, key.categ)");
System.out.println(node.toPrettyString());
Output
[ {
"ID" : [ "id1", "id2" ],
"ref" : "ref1",
"categ" : "CATEG_A"
}, {
"ID" : [ "id3" ],
"ref" : "ref1",
"categ" : "CATEG_B"
} ]

Related

UpperCase all json keys using java and regex to find the matches

I'm beginner in java and have to replace all json Keys to upper Case .
My json can contain arrays (maybe nested Ones) and objects
Here is an example of my json input :
{
"transactionId": 181,
"Shipments": [
{
"shipmentId": 2,
"picklistId": "24RZ",
"ExtOrderId": "23-127",
"boxType": "120"
}
]
}
Here is an example of my json Output :
{
"TRANSACTIONID": 181,
"SHIPMENTS": [
{
"SHIPMENTID": 2,
"PICKLISTID": "24RZ",
"EXTORDERID": "23-127",
"BOXTYPE": "120"
}
]
}
I have tried to create an adapter but no chance to make it work correctly ,
Do i Have to use a regex and a replaceAll("everything before a : " , "upperCase()")
I'm reaching out to you guys to help me on this task because i could not find a way out to find a solution
One of the solutions is to flatten the JSON, upperCase() the keys and unflatten the JSON. Library Josson can do the transformation.
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(
"{" +
" \"transactionId\": 181," +
" \"Shipments\": [" +
" {" +
" \"shipmentId\": 2," +
" \"picklistId\": \"24RZ\"," +
" \"ExtOrderId\": \"23-127\"," +
" \"boxType\": \"120\"" +
" }" +
" ]" +
"}");
JsonNode node = josson.getNode(
"flatten('.').entries().map(key.upperCase()::value).mergeObjects().unflatten('.')");
System.out.println(node.toPrettyString());
Output
{
"TRANSACTIONID" : 181,
"SHIPMENTS" : [ {
"SHIPMENTID" : 2,
"PICKLISTID" : "24RZ",
"EXTORDERID" : "23-127",
"BOXTYPE" : "120"
} ]
}

Querying JSON Object in Java

Suppose my JSON is :
{
"Name" : "Anmol Jain",
"Address" : [
{
"type" : "home",
"category" : "primary",
"street" : "ABC"
},
{
"type" : "home",
"category" : "secondary",
"street" : "XYZ"
},
{
"type" : "work",
"category" : "primary",
"street" : "PQR"
}
]
}
I am designing a specific syntax for my project so that I can query the JSON.
For Example :
Address(type = home; category = secondary).street
this should give me result as "XYZ".
The first approach that comes to my mind is to parse the above code syntax, and look for conditions like type and category (by string parsing).
then loop through Address array and try to match those conditions. But this will give higher time complexity in case of large JSONs.
Is there any library which does that. Or if anyone can suggest me better approach. The syntax for the condition is flexible and I can mould it accordingly.
Thanks in advance.
For example, use library "Josson & Jossons"
https://github.com/octomix/josson
implementation 'com.octomix.josson:josson:1.3.22'
------------------------------------------------
Josson josson = Josson.fromJsonString(
"{" +
" \"Name\" : \"Anmol Jain\"," +
" \"Address\" : [" +
" {" +
" \"type\" : \"home\"," +
" \"category\" : \"primary\"," +
" \"street\" : \"ABC\"" +
" }," +
" {" +
" \"type\" : \"home\"," +
" \"category\" : \"secondary\"," +
" \"street\" : \"XYZ\"" +
" }," +
" {" +
" \"type\" : \"work\"," +
" \"category\" : \"primary\"," +
" \"street\" : \"PQR\"" +
" }" +
" ]" +
"}");
String street = josson.getString("Address[type='home' & category='secondary'].street");
Besides #tgdavies mentioned, also have a look at https://github.com/eiiches/jackson-jq, it uses the same syntax of jq, but in java implementation.

Transform JSON and create new one

I'm working with JSON in Java, and I want to trasnform a JSON I have as entry :
{
"index":{
"mutlipleIndices":[
{
"index":"languages",
"values":[
"English",
"German"
]
},
{
"index":"editors",
"values":[
"AC. Renus",
"Lodiga"
]
}
],
"simpleIndices":[
{
"index":"bookName",
"values":"A song Of Ice and fire"
},
{
"index":"nbPages",
"valeurs":1600
}
]
}
}
int this :
{
"data": { ... Put here the entry JSON ... },
"flatData": [
{
"key": "languages",
"type": "string",
"key_type": "languages.string",
"value_string": ["English", "German"]
},
{
"key": "editors",
"type": "string",
"key_type": "editors.string",
"value_string": ["AC. Renus", "Lodiga"]
},
{
"key": "bookName",
"type": "string",
"key_type": "bookName.string",
"value_string": "A song Of Ice and fire"
},
{
"key": "nbPages",
"type": "float",
"key_type": "nbPages.float",
"value_float": 1600
}
]
}
My entry JSON is a JsonNode (Jackson library), how can I iterate on that object and create a new one ?
Basically what I thought I'd do is iternate on the entry json, find an entry and transform it
Thanks in advance
Create 2 pojos
Mapping the input json (let's call it MyJsonInput.java)
Mapping the output you want (let's call it MyOutputObject.java).
These 2 classes should have fields which matches the json structure.
Create a mapper:
ObjectMapper objectMapper = new ObjectMapper();
Read the json and translate it into your object:
MyJsonInput myInput = objectMapper.readValue(json, MyJsonInput.class); //where json is a string with the content of your json file.
Now you have a MyJsonInput instance (myInput) containing the json data and you can do your logic to flatten it and fill your MyOutputObject.
To get the json string of MyOutputObject instance use:
String outputAsString = objectMapper.writeValueAsString(myOutputObject);
You can also threat your both input and output as a generic Map<String,Object> but in my opinion not the best way because it can get very complicated reading and parsing maps containing other maps, and not to mention that you need to cast your data into the appropriate type (string, number etc..)
https://github.com/octomix/josson
https://mvnrepository.com/artifact/com.octomix.josson/josson
implementation 'com.octomix.josson:josson:1.3.21'
-------------------------------------------------
Jossons jossons = new Jossons();
jossons.putDataset("input", Josson.fromJsonString(
"{\n" +
" \"index\":{\n" +
" \"multipleIndices\":[\n" +
" {\n" +
" \"index\":\"languages\",\n" +
" \"values\":[\n" +
" \"English\",\n" +
" \"German\"\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"index\":\"editors\",\n" +
" \"values\":[\n" +
" \"AC. Renus\",\n" +
" \"Lodiga\"\n" +
" ]\n" +
" }\n" +
" ],\n" +
" \"simpleIndices\":[\n" +
" {\n" +
" \"index\":\"bookName\",\n" +
" \"values\":\"A song Of Ice and fire\"\n" +
" },\n" +
" {\n" +
" \"index\":\"nbPages\",\n" +
" \"values\":1600\n" +
" }\n" +
" ]\n" +
" }\n" +
"}"));
Map<String, String> dictionaryFinder = new HashMap<>();
// Define a dictionary function, $0 is the function parameter.
dictionaryFinder.put("flatIndices()",
"$0->map(" +
"key:index," +
"type:if(values.isArray(),values[0],values).if(isText(),'string','float')," +
"key_type:concat(index,'.',if(values.isArray(),values[0],values).if(isText(),'string','float'))," +
"value_string:values)");
// Define a left concatenate operation to combine two arrays.
dictionaryFinder.put("allIndices",
"flatIndices(input->index.multipleIndices) <+< flatIndices(input->index.simpleIndices)");
ResolverProgress progress = new ResolverProgress("\nProgress:");
// The query is a left concatenate operation to combine two objects.
JsonNode output = jossons.evaluateQueryWithResolver(
"input->toObject('data') <+< allIndices->toObject('flatData')",
dictionaryFinder::get, null, progress);
// Print result.
System.out.println(output == null ? null : output.toPrettyString());
// Print resolution progress.
System.out.println(String.join("\n", progress.getSteps()));
Output
{
"data" : {
"index" : {
"multipleIndices" : [ {
"index" : "languages",
"values" : [ "English", "German" ]
}, {
"index" : "editors",
"values" : [ "AC. Renus", "Lodiga" ]
} ],
"simpleIndices" : [ {
"index" : "bookName",
"values" : "A song Of Ice and fire"
}, {
"index" : "nbPages",
"values" : 1600
} ]
}
},
"flatData" : [ {
"key" : "languages",
"type" : "string",
"key_type" : "languages.string",
"value_string" : [ "English", "German" ]
}, {
"key" : "editors",
"type" : "string",
"key_type" : "editors.string",
"value_string" : [ "AC. Renus", "Lodiga" ]
}, {
"key" : "bookName",
"type" : "string",
"key_type" : "bookName.string",
"value_string" : "A song Of Ice and fire"
}, {
"key" : "nbPages",
"type" : "float",
"key_type" : "nbPages.float",
"value_string" : 1600
} ]
}
Progress:
Round 1 : Resolving allIndices from flatIndices(input->index.multipleIndices) <+< flatIndices(input->index.simpleIndices)
Round 1 : Resolving flatIndices(input->index.multipleIndices) from $0->map(key:index,type:if(values.isArray(),values[0],values).if(isText(),'string','float'),key_type:concat(index,'.',if(values.isArray(),values[0],values).if(isText(),'string','float')),value_string:values)
Round 1 : Resolved flatIndices(input->index.multipleIndices) = Array with 2 elements
Round 2 : Resolving flatIndices(input->index.simpleIndices) from $0->map(key:index,type:if(values.isArray(),values[0],values).if(isText(),'string','float'),key_type:concat(index,'.',if(values.isArray(),values[0],values).if(isText(),'string','float')),value_string:values)
Round 2 : Resolved flatIndices(input->index.simpleIndices) = Array with 2 elements
Round 3 : Resolved allIndices = Array with 4 elements
Round 4 : Resolved query result = Object with 2 elements

How to merge two JSON string

I have two JSON strings, I want to merge these two response string into a single one. Is there any way to merge these two JSON string using java ?
String str1 = "{
"data" : {
"values" : {
"name" : "kiran",
"age" : "24"
}
}
}"
String str2 = "{
"data" : {
"values" : {
"name" : "Mamu",
"age" : "26"
}
}
}"
I wnat to merge these two JSON string as follows
String mergeResult = "{
"data" : {
"values" : [
{
"name" : "kiran",
"age" : "24"
},
{
"name" : "Manu",
"age" : "26"
}
]
}
}"
From your example JSON it looks like there can be many more input objects than two, so I'd use a JSON to JSON transform via JOLT library (https://github.com/bazaarvoice/jolt) as follows:
Form a JSON array of all the input {"data" : ...} objects (either by collecting the original objects and putting them in a List before serialization or just manually by concatenating their JSONs with square brackets):
[
{
"data": {
"values": {
"name": "kiran",
"age": "24"
}
}
},
{
"data": {
"values": {
"name": "Mamu",
"age": "26"
}
}
}
]
Use the JOLT spec:
[
{
"operation": "shift",
"spec": {
"*": {
"data": {
"values": {
"#": "data.values[]"
}
}
}
}
}
]
The resulting JSON:
{
"data" : {
"values" : [ {
"name" : "kiran",
"age" : "24"
}, {
"name" : "Mamu",
"age" : "26"
} ]
}
}
You can test or modify the spec yourself at http://jolt-demo.appspot.com before using it in your application.
Here's what Java side might look like:
Resource transformationSpec = ...
String inputJson = ...
List<Object> specs = JsonUtils.jsonToList(transformationSpec.getInputStream());
Chainr chainr = Chainr.fromSpec(specs);
Object inputObject = JsonUtils.jsonToObject(inputJson);
Object transformedObject = chainr.transform(inputObject);
String transformedJson = JsonUtils.toJsonString(transformedObject);
Library Josson & Jossons has concatenate operation to combine array from datasets.
https://github.com/octomix/josson
Jossons jossons = new Jossons();
jossons.putDataset("resp1", Josson.fromJsonString(
"{" +
" \"data\": {" +
" \"values\": {" +
" \"name\": \"kiran\"," +
" \"age\": \"24\"" +
" }" +
" }" +
"}"));
jossons.putDataset("resp2", Josson.fromJsonString(
"{" +
" \"data\": {" +
" \"values\": {" +
" \"name\": \"Mamu\"," +
" \"age\": \"26\"" +
" }" +
" }" +
"}"));
JsonNode mergeValues = jossons.evaluateQuery(
"resp1->data.toArray() <+< resp2->data.toArray()");
System.out.println(mergeValues.toPrettyString());
JsonNode mergeResult = Josson.create(mergeValues).getNode(
"toObject('values').toObject('data')");
System.out.println(mergeResult.toPrettyString());
mergeValues
[ {
"name" : "kiran",
"age" : "24"
}, {
"name" : "Mamu",
"age" : "26"
} ]
mergeResult
{
"data" : {
"values" : [ {
"name" : "kiran",
"age" : "24"
}, {
"name" : "Mamu",
"age" : "26"
} ]
}
}
May be not the most efficient solution but very simple one would be to parse each String into a Map (or specific POJO if you have one) and merge them as maps, and than serialize back into Json String. To parse a json string to map or a specific POJO you can use Jackson library - method readValue() of ObjectMapper Or Gson library. Also, I wrote my own simple wrapper over Jackson library that simplifies the use. Class JsonUtils is available as part of MgntUtils library (written and maintained by me). This class just has the methods that allow you to parse and de-serialize from/to Json String from/to a class instance. So your code could be as follows:
public String mergeJsonStrings(String str1, Str2) throws IOException {
Map<String, Object> map1 = convertJsonStringToMap(str1);
Map<String, Object> map2 = convertJsonStringToMap(str2);
Map<String, Object> dataMap1 = (Map<String, Object>)map1.get("data");
Map<String, Object> valuesMap1 = (Map<String, Object>)dataMap1.get("values");
Map<String, Object> dataMap2 = (Map<String, Object>)map2.get("data");
Map<String, Object> valuesMap2 = (Map<String, Object>)dataMap2.get("values");
valuesMap1.putAll(valuesMap2);
return convertMapToJsonString(map1);
}
Map<String, Object> convertJsonStringToMap(String str) throws IOException {
return JsonUtils.readObjectFromJsonString(str, Map.class);
}
Strong convertMapToJsonString(Map<String,Object> map) throws JsonProcessingException{
return JsonUtils.writeObjectToJsonString(map);
}
This example uses MgntUtils library to parse and serialize JSON but of course you can use Jackson, Gson or any other library you want. MgntUtils library available as Maven artifact and on Github (including source code and Javadoc)

Read out elements of a string in specific order

For some reasons I have to use a specific string in my project. This is the text file (it's a JSON File):
{"algorithm":
[
{ "key": "onGapLeft", "value" : "moveLeft" },
{ "key": "onGapFront", "value" : "moveForward" },
{ "key": "onGapRight", "value" : "moveRight" },
{ "key": "default", "value" : "moveBackward" }
]
}
I've defined it in JAVA like this:
static String input = "{\"algorithm\": \n"+
"[ \n" +
"{ \"key\": \"onGapLeft\", \"value\" : \"moveLeft\" }, \n" +
"{ \"key\": \"onGapFront\", \"value\" : \"moveForward\" }, \n" +
"{ \"key\": \"onGapRight\", \"value\" : \"moveRight\" }, \n" +
"{ \"key\": \"default\", \"value\" : \"moveBackward\" } \n" +
"] \n" +
"}";
Now I have to isolate the keys and values in an array:
key[0] = onGapLeft; value[0] = moveLeft;
key[1] = onGapFront; value[1] = moveForward;
key[2] = onGapRight; value[2] = moveRight;
key[3] = default; value[3] = moveBackward;
I'm new to JAVA and don't understand the string class very well. Is there an easy way to get to that result? You would help me really!
Thanks!
UPDATE:
I didn't explained it well enough, sorry. This program will run on a LEGO NXT Robot. JSON won't work there as I want it to so I have to interpret this JSON File as a normal STRING! Hope that explains what I want :)
I propose a solution in several step.
1) Let's get the different parts of your ~JSON String. We will use a pattern to get the different {.*} parts :
public static void main(String[] args) throws Exception{
List<String> lines = new ArrayList<String>();
Pattern p = Pattern.compile("\\{.*\\}");
Matcher matcher = p.matcher(input);
while (matcher.find()) {
lines.add(matcher.group());
}
}
(you should take a look at Pattern and Matcher)
Now, lines contains 4 String :
{ "key": "onGapLeft", "value" : "moveLeft" }
{ "key": "onGapFront", "value" : "moveForward" }
{ "key": "onGapRight", "value" : "moveRight" }
{ "key": "default", "value" : "moveBackward" }
Given a String like one of those, you can remove curly brackets with a call to String#replaceAll();
List<String> cleanLines = new ArrayList<String>();
for(String line : lines) {
//replace curly brackets with... nothing.
//added a call to trim() in order to remove whitespace characters.
cleanLines.add(line.replaceAll("[{}]","").trim());
}
(You should take a look at String String#replaceAll(String regex))
Now, cleanLines contains :
"key": "onGapLeft", "value" : "moveLeft"
"key": "onGapFront", "value" : "moveForward"
"key": "onGapRight", "value" : "moveRight"
"key": "default", "value" : "moveBackward"
2) Let's parse one of those lines :
Given a line like :
"key": "onGapLeft", "value" : "moveLeft"
You can split it on , character using String#split(). It will give you a String[] containing 2 elements :
//parts[0] = "key": "onGapLeft"
//parts[1] = "value" : "moveLeft"
String[] parts = line.split(",");
(You should take a look at String[] String#split(String regex))
Let's clean those parts (remove "") and assign them to some variables:
String keyStr = parts[0].replaceAll("\"","").trim(); //Now, key = key: onGapLeft
String valueStr = parts[1].replaceAll("\"","").trim();//Now, value = value : moveLeft
//Then, you split `key: onGapLeft` with character `:`
String key = keyStr.split(":")[1].trim();
//And the same for `value : moveLeft` :
String value = valueStr.split(":")[1].trim();
That's it !
You should also take a look at Oracle's tutorial on regular expressions (This one is really important and you should invest time on it).
You need to use a JSON parser library here. For example, with org.json you could parse it as
String input = "{\"algorithm\": \n"+
"[ \n" +
"{ \"key\": \"onGapLeft\", \"value\" : \"moveLeft\" }, \n" +
"{ \"key\": \"onGapFront\", \"value\" : \"moveForward\" }, \n" +
"{ \"key\": \"onGapRight\", \"value\" : \"moveRight\" }, \n" +
"{ \"key\": \"default\", \"value\" : \"moveBackward\" } \n" +
"] \n" +
"}";
JSONObject root = new JSONObject(input);
JSONArray map = root.getJSONArray("algorithm");
for (int i = 0; i < map.length(); i++) {
JSONObject entry = map.getJSONObject(i);
System.out.println(entry.getString("key") + ": "
+ entry.getString("value"));
}
Output :
onGapLeft: moveLeft
onGapFront: moveForward
onGapRight: moveRight
default: moveBackward

Categories