How can i remove a line in a JSON in JAVA - java

My JSON:
{
"adresses": [
{
"region": "Auvergne-Rhône-Alpes",
"pertinence": 0.41,
"cp": "73200",
"coordonnee": [
45.6681753,
6.3863336
],
"rue": "Rue Pasteur",
"osm_id": "8063355",
"pays": "France",
"ville": "Albertville",
"quartier": "Le Parstet",
"nom": "",
"secteur": "Albertville",
"numero": ""
},
{
"region": "Auvergne-Rhône-Alpes",
"pertinence": 0.41,
"cp": "73200",
"coordonnee": [
45.6635769,
6.3830012
],
"rue": "Rue Pasteur",
"osm_id": "69253010",
"pays": "France",
"ville": "Albertville",
"quartier": "",
"nom": "",
"secteur": "Albertville",
"numero": ""
},
{
"region": "Auvergne-Rhône-Alpes",
"pertinence": 0.41,
"cp": "73400",
"coordonnee": [
45.7469095,
6.4237485
],
"rue": "Rue Pasteur",
"osm_id": "170250718",
"pays": "France",
"ville": "Ugine",
"quartier": "",
"nom": "",
"secteur": "Albertville",
"numero": ""
}
]
}
I need to remove one of adresses when "osm_id" is equals to a variable.
I have started to put the JSON in a ArrayList string for delete the line I want then redo the JSON.
But element "coordonnee" is an array, and i don't know who can i do.
Here my trial :
JSONObject req = reponse.convertToJsonObject();
JSONArray adresses = req.getJSONArray( "adresses" );
ArrayList<String> tab = new ArrayList<String>();
for ( int i = 0; i < adresses.length(); i++ ) {
JSONObject adr = adresses.getJSONObject( i );
String line = adr.getString( "region" ) + " " + adr.getDouble( "pertinence" ) + " "
+ adr.getString( "cp" ) + " " + adr.getString( "coordonnee" )
+ " " + adr.getString( "rue" ) + " " + adr.getString( "osm_id" ) + " "
+ adr.getString( "pays" ) + " " + adr.getString( "ville" )
+ " " + adr.getString( "quartier" ) + " " + adr.getString( "nom" ) + " "
+ adr.getString( "secteur" ) + " " + adr.getString( "numero" );
tab.add( line );
}
Can you help me ?

I think this should do what you want. It will filter out any addresses that have an "osm_id" matching your provided variable.
JSONObject req = reponse.convertToJsonObject();
JSONArray filteredAddresses = new JSONArray();
String filterId = "..."; // put whatever your ID is here
JSONArray unfilteredAddresses = req.getJSONArray("adresses");
for (int i = 0; i < unfilteredAddresses.length(); i++){
JSONObject addressJson = unfilteredAddresses.getJSONObject(i);
if (!addressJson.has("osm_id") || !addressJson.getString("osm_id").equals(filterId)){
filteredAddresses.put(addressJson);
}
}
req.put("adresses", filteredAddresses);

Related

Json manipulation and conversion in Java

I have an input json like:
{
"Employee": [
{
"employee1.id": 1
},
{
"employee1.name": "John"
},
{
"employee1.address.street": "main street"
},
{
"employee1.address.pin": "123456"
},
{
"employee2.id": 2
},
{
"employee2.name": "Mike"
},
{
"employee2.address.street": "51 street"
},
{
"employee2.address.pin": "234543"
}
]
}
And I am trying to convert it into:
{
"employee1":{
"id": 1,
"name": "John",
"address": {
"street": "main street",
"pin": "123456"
}
},
"employee2":{
"id": 2,
"name": "Mike",
"address": {
"street": "51 street",
"pin": "234543"
}
}
}
I tried to split the key from input json with dot i.e. '.' and tried to iterate over to construct a map: Map<String, Object>
But the problem is the input json key depth can go beyond 2 i.e. in future the input key can be like:
{
"employee1.address.tempAddress.street": "main street"
},
{
"employee1.address.permanentAddress.street": "main street"
}
So, is there any library available to achieve this, or anything closely related to this using which I can achieve this?
The comments about the input format being "weird" (to put it politely) are spot-on: This is a convoluted way to represent simple hierarchical data.
But sometimes we have to deal with sub-optimal input formats, that's why we can fix them like this:
private static JSONObject arrayToStructure(JSONArray inputArray) {
JSONObject output = new JSONObject();
for (Object o : inputArray) {
assert o instanceof JSONObject;
JSONObject jso = (JSONObject) o;
assert jso.length() == 1;
String key = jso.keys().next();
Object value = jso.get(key);
setJsonPath(output, key, value);
}
return output;
}
private static void setJsonPath(JSONObject target, String key, Object value) {
String[] keyParts = key.split("\\.");
JSONObject parent = target;
for (int i = 0; i < keyParts.length - 1; i++) {
String keyPart = keyParts[i];
if (parent.has(keyPart)) {
parent = parent.getJSONObject(keyPart);
} else {
JSONObject child = new JSONObject();
parent.put(keyPart, child);
parent = child;
}
}
assert !parent.has(keyParts[keyParts.length - 1]);
parent.put(keyParts[keyParts.length - 1], value);
}
This code uses JSON-Java, probably better known as org.json:json.
And it can be used like this:
public static void main(String[] args) {
String input = """
[
{
"employee1.id": 1
},
{
"employee1.name": "John"
},
{
"employee1.address.street": "main street"
},
{
"employee1.address.pin": "123456"
},
{
"employee2.id": 2
},
{
"employee2.name": "Mike"
},
{
"employee2.address.street": "51 street"
},
{
"employee2.address.pin": "234543"
}
]""";
JSONArray inputArray = new JSONArray(input);
JSONObject structure = arrayToStructure(inputArray);
System.out.println(structure.toString(2));
}
Note that this code is lacking proper sanity checks (some of which I've hinted at using assert) and the nature of this "protocol" means that you can get misleading, ambiguous or straight up malicious inputs. For example nothing stops the input from having both "employee1.id": 1 and "employee1.id": 2 in there. How that is to be interpreted is up to the parser and such ambiguity is a great source of bugs and potential security issues.
Library Josson can do the transformation by one expression.
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(
"{" +
" \"Employee\": [" +
" {" +
" \"employee1.id\": 1" +
" }," +
" {" +
" \"employee1.name\": \"John\"" +
" }," +
" {" +
" \"employee1.address.street\": \"main street\"" +
" }," +
" {" +
" \"employee1.address.pin\": \"123456\"" +
" }," +
" {" +
" \"employee2.id\": 2" +
" }," +
" {" +
" \"employee2.name\": \"Mike\"" +
" }," +
" {" +
" \"employee2.address.street\": \"51 street\"" +
" }," +
" {" +
" \"employee2.address.pin\": \"234543\"" +
" }" +
" ]" +
"}");
JsonNode node = josson.getNode("Employee.mergeObjects().unflatten('.')");
System.out.println(node.toPrettyString());
Output
{
"employee1" : {
"id" : 1,
"name" : "John",
"address" : {
"street" : "main street",
"pin" : "123456"
}
},
"employee2" : {
"id" : 2,
"name" : "Mike",
"address" : {
"street" : "51 street",
"pin" : "234543"
}
}
}

Getting the values of a specific key from JsonNode

I have a JsonNode result represented as:
[
{
"item": {
"type": "uri",
"value": "http://www.wikidata.org/entity/Q42442324"
},
"prop": {
"type": "uri",
"value": "http://www.wikidata.org/prop/direct/P21"
},
"itemLabel": {
"xml:lang": "en",
"type": "literal",
"value": "Kiisu Miisu"
}
},
{
"item": {
"type": "uri",
"value": "http://www.wikidata.org/entity/Q43260736"
},
"prop": {
"type": "uri",
"value": "http://www.wikidata.org/prop/direct/P21"
},
"itemLabel": {
"xml:lang": "en",
"type": "literal",
"value": "Paddles"
}
}
]
I am trying to retieve the values of the key "value" into an array list using the below code but am getting the error
Cannot invoke "com.fasterxml.jackson.databind.JsonNode.findValue(String)" because the return value of "com.fasterxml.jackson.databind.JsonNode.get(int)" is null
for (int i = 0; i < resultSize; i++) {
JsonNode jsonObject = results.get(i);
if (indexRow < jsonObject.size()) {
jsonRows = Collections.singletonList(jsonObject.get(indexRow++).findValue("value").asText());
}
}
The value of variable jsonObject in the first iteration from the debugger is
{
"item": {
"type": "uri",
"value": "http://www.wikidata.org/entity/Q42442324"
},
"prop": {
"type": "uri",
"value": "http://www.wikidata.org/prop/direct/P21"
},
"itemLabel": {
"xml:lang": "en",
"type": "literal",
"value": "Kiisu Miisu"
}
}
Expected output is
[
"http://www.wikidata.org/entity/Q42442324",
"http://www.wikidata.org/entity/Q42442324",
"Kiisu Miisu",
"http://www.wikidata.org/entity/Q43260736",
"http://www.wikidata.org/prop/direct/P21",
"Paddles"
]
You can use elements() method and check if value key exist then add the value to list.
Smaple code
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(data);
List<String> values = new ArrayList<>();
jsonNode.forEach(jsonObject -> jsonObject.elements().forEachRemaining(valueNode -> {
if(valueNode.has("value"))
values.add(valueNode.get("value").asText());
}));
System.out.println(values);
Output:
[http://www.wikidata.org/entity/Q42442324, http://www.wikidata.org/prop/direct/P21, Kiisu Miisu, http://www.wikidata.org/entity/Q43260736, http://www.wikidata.org/prop/direct/P21, Paddles]
Here is the solution by "Josson & Jossons". I list 2 more examples with condition filtering.
https://github.com/octomix/josson
implementation 'com.octomix.josson:josson:1.3.22'
---------------------------------------------
Josson josson = Josson.fromJsonString(
"[" +
" {" +
" \"item\": {" +
" \"type\": \"uri\", \"value\": \"http://www.wikidata.org/entity/Q42442324\"" +
" }," +
" \"prop\": {" +
" \"type\": \"uri\", \"value\": \"http://www.wikidata.org/prop/direct/P21\"" +
" }," +
" \"itemLabel\": {" +
" \"xml:lang\": \"en\", \"type\": \"literal\", \"value\": \"Kiisu Miisu\"" +
" }" +
" }," +
" {" +
" \"item\": {" +
" \"type\": \"uri\", \"value\": \"http://www.wikidata.org/entity/Q43260736\"" +
" }," +
" \"prop\": {" +
" \"type\": \"uri\", \"value\": \"http://www.wikidata.org/prop/direct/P21\"" +
" }," +
" \"itemLabel\": {" +
" \"xml:lang\": \"en\", \"type\": \"literal\", \"value\": \"Paddles\"" +
" }" +
" }" +
"]");
JsonNode node = josson.getNode("*.value");
System.out.println("1.\n" + node.toPrettyString());
node = josson.getNode("~'^item.*'.value");
System.out.println("2.\n" + node.toPrettyString());
node = josson.getNode("*[value.type='uri']*.value");
System.out.println("3.\n" + node.toPrettyString());
Output:
1.
[ "http://www.wikidata.org/entity/Q42442324", "http://www.wikidata.org/prop/direct/P21", "Kiisu Miisu", "http://www.wikidata.org/entity/Q43260736", "http://www.wikidata.org/prop/direct/P21", "Paddles" ]
2.
[ "http://www.wikidata.org/entity/Q42442324", "Kiisu Miisu", "http://www.wikidata.org/entity/Q43260736", "Paddles" ]
3.
[ "http://www.wikidata.org/entity/Q42442324", "http://www.wikidata.org/prop/direct/P21", "http://www.wikidata.org/entity/Q43260736", "http://www.wikidata.org/prop/direct/P21" ]

Add json inner object

I have the following code
JSONArray jobj = new select_data().get_patient_summary(p_id);
JSONObject jInnerObject = new JSONObject();
jInnerObject.put("weight", weight.get(0));
jobj.put(jInnerObject);
The outcome is:
{
"data": [
{
"pre_transfusional_haemoglobin_level": "",
"rhesus_blood_group_system": "",
"patient_id": "1",
"surname": "Demetriou",
"DOB": "2004-02-04",
"health_insurance_information": "ac",
"name": "Andreas",
"blood_group": "",
"transfusion_frequency": ""
},
{
"weight": "90"
}
],
"success": 1
}
Can I insert "weight" in the previous string, like:
{
"data": [
{
"pre_transfusional_haemoglobin_level": "",
"rhesus_blood_group_system": "",
"patient_id": "1",
"surname": "Demetriou",
"DOB": "2004-02-04",
"health_insurance_information": "ac",
"name": "Andreas",
"blood_group": "",
"transfusion_frequency": "",
"weight": "90"
},
],
"success": 1
}
EDITED for complete executable code:
import org.json.JSONObject;
public class test {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
String input = "{\r\n" +
" \"data\": [\r\n" +
" {\r\n" +
" \"pre_transfusional_haemoglobin_level\": \"\",\r\n" +
" \"rhesus_blood_group_system\": \"\",\r\n" +
" \"patient_id\": \"1\",\r\n" +
" \"surname\": \"Demetriou\",\r\n" +
" \"DOB\": \"2004-02-04\",\r\n" +
" \"health_insurance_information\": \"ac\",\r\n" +
" \"name\": \"Andreas\",\r\n" +
" \"blood_group\": \"\",\r\n" +
" \"transfusion_frequency\": \"\"\r\n" +
" },\r\n" +
" ],\r\n" +
" \"success\": 1\r\n" +
"}";
JSONObject jobj = new JSONObject(input);
jobj.getJSONArray("data").getJSONObject(0).put("weight", 90);
System.out.println(jobj.toString(1));
}
}

Build new json string using a json template file and a json data file

I have a json template file as below
{
"value": "abc",
"Treatments": [{
"value": "def",
"Stages": [{
"value": "ghi"
}]
}]
}
And a json data
{ "abc": {
"labelabc": "Assembly name abc",
"typeabc": "STRING_TYPE abc",
"formatabc": "N abc"
},
"def": {
"labeldef": "Assembly name def",
"typedef": "STRING_TYPE def",
"formatdef": "N def"
},
"ghi": {
"labelghi": "Assembly name ghi",
"typeghi": "STRING_TYPE ghi",
"formatghi": "N ghi"
}
}
I'm looking for a solution to parse the template into
{
"labelabc": "Assembly name abc",
"typeabc": "STRING_TYPE abc",
"formatabc": "N abc",
"Treatments": [
{
"labeldef": "Assembly name def",
"typedef": "STRING_TYPE def",
"formatdef": "N def",
"Stages": [
{
"labelghi": "Assembly name ghi",
"typeghi": "STRING_TYPE ghi",
"formatghi": "N ghi"
}
]
}
]
}
Meant:
Replace "value" entry with the jsonobject value in json data file
I already used the code below to achieve the result with 2 levels template. But failed with above 3 levels template
public static JsonElement generateTemplate(JsonElement templateJson, JsonElement dataTemplate) {
if (templateJson.isJsonArray()) {
for (JsonElement jsonElement1 : templateJson.getAsJsonArray()) {
generateTemplate(jsonElement1, dataTemplate);
}
} else if (templateJson.isJsonObject()) {
for (Iterator<Map.Entry<String, JsonElement>> iterator = templateJson.getAsJsonObject().entrySet()
.iterator(); iterator.hasNext();) {
Map.Entry<String, JsonElement> entry = iterator.next();
if (entry.getKey().equals("value")) {
templateJson = dataTemplate.getAsJsonObject().get(entry.getValue().getAsString()).getAsJsonObject();
} else {
if (entry.getValue().isJsonObject()) {
generateTemplate(entry.getValue(), dataTemplate);
} else
templateJson.getAsJsonObject().add(entry.getKey(), p.parse(
dataTemplate.getAsJsonObject().get(entry.getValue().getAsString()).getAsJsonObject()
));
}
generateTemplate(entry.getValue(), dataTemplate);
}
}
return templateJson;
}
Very appreciated your advices
You could use recursion. This is main idea, you can adjust actual replacements according to your needs later in modifyObject method which for "value": "abc" would expect object held in data under
"abc": {
"labelabc": "Assembly name abc",
"typeabc": "STRING_TYPE abc",
"formatabc": "N abc"
}
private static void modifyObject(JsonObject obj, JsonObject replacement) {
obj.remove("value");
for (String key : replacement.keySet()) {
obj.addProperty(key, replacement.get(key).getAsString());
}
}
public static JsonElement traverse(JsonElement element, JsonObject allReplacements) {
if (element.isJsonObject()) {
JsonObject asJsonObject = element.getAsJsonObject();
///keys can change after we modify object,
//but we want to iterate only over original keys
Set<String> originalKeys = new HashSet<>(asJsonObject.keySet());
for (String key : originalKeys) {
if (key.equals("value")) {
String value = asJsonObject.get(key).getAsString();
modifyObject(asJsonObject, allReplacements.getAsJsonObject(value));
} else {
traverse(asJsonObject.get(key), allReplacements);
}
}
} else if (element.isJsonArray()) {
for (JsonElement innerElement : element.getAsJsonArray()) {
traverse(innerElement, allReplacements);
}
}
return element;
}
Usage:
public static void main(String[] args) throws Exception {
String jsonTemplate =
"{\n" +
" \"value\": \"abc\",\n" +
" \"foo\": \"bar\",\n" +
" \"Treatments\": [ {\n" +
" \"value\": \"def\",\n" +
" \"Stages\": [ [ {\n" +
" \"value\": \"ghi\"\n" +
" } ] ]\n" +
" } ]\n" +
"}";
String jsonData = "{ \"abc\": {\n" +
" \"label\": \"Assembly name abc\",\n" +
" \"type\": \"STRING_TYPE abc\",\n" +
" \"format\": \"N\"\n" +
" },\n" +
" \"def\": {\n" +
" \"label\": \"Assembly name def\",\n" +
" \"type\": \"STRING_TYPE\",\n" +
" \"format\": \"N\"\n" +
" },\n" +
" \"ghi\": {\n" +
" \"label\": \"Assembly name ghi\",\n" +
" \"type\": \"STRING_TYPE\",\n" +
" \"format\": \"N\"\n" +
" }\n" +
"}";
JsonParser jsonParser = new JsonParser();
JsonElement template = jsonParser.parse(jsonTemplate);
JsonObject data = (JsonObject) jsonParser.parse(jsonData);
JsonElement obj = template.deepCopy();//in case we don't want to modify original template
Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println(gson.toJson(traverse(obj, data)));
}
Output:
{
"foo": "bar",
"Treatments": [
{
"Stages": [
[
{
"label": "Assembly name ghi",
"type": "STRING_TYPE",
"format": "N"
}
]
],
"label": "Assembly name def",
"type": "STRING_TYPE",
"format": "N"
}
],
"label": "Assembly name abc",
"type": "STRING_TYPE abc",
"format": "N"
}

How to extract specific data from json with multiple nodes?

Using java with selenium
I have captured full json in my code
IN my json there are two nodes "Service1" and "Service2"
My requirement is to fetch the details of "Services1" node -->data node
But i am not able to extract only Service1 with data node details(i do not want "test" node details.
Question: Can you please help me to extract data from Service1-with data node only using java code?I am using selenium with java.I need this for one of the script.
Actual response:
{
"Service1": [
{
"data": {
"status": false,
"type": "A",
"order": 1,
"Version": "v6"
},
"test": {
"ModuleID": "123456",
"BoxID": "a777",
"Url": "https://google.com"
}
},
{
"data": {
"status": true,
"type": "B",
"order": 1,
"Version": "v2"
},
"test": {
"ModuleID": "123456",
"BoxID": "a777",
"Url": "https://google.com"
}
}
],
"Service2": {
"data1": {
"status": false,
"type": "c",
"order": 1,
"Version": "v6"
},
"dashboard": {
"ModuleID": "123456",
"BoxID": "a777",
"Url": "https://google.com"
}
}
}
Expected data :
[
{
"status": false,
"type": "A",
"order": 1,
"Version": "v6"
},
{
"status": true,
"type": "B",
"order": 1,
"Version": "v2"
}
]
Fetching the required data is based on the api response. But in the result of the fetched data you can convert it as you want in java as:
Main theme:
JSONObject response = new JSONObject("json data");//replace json data with your given json data
JSONArray service1 = response.getJSONArray("Service1");
JSONObject firstObjectInService1 = service1.getJSONObject(0);
JSONObject secondObjectInService1 = service1.getJSONObject(1);
JSONObject dataInFirstObject = firstObjectInService1.getJSONObject("data");
JSONObject dataInSecondObject = secondObjectInService1.getJSONObject("data");
Full code snippet:
import org.json.*;
public class JsonParsing {
public static void main(String[] args) {
String jsonData = "{\n" +
"\"Service1\": [\n" +
" {\n" +
" \"data\": {\n" +
" \"status\": false,\n" +
" \"type\": \"A\",\n" +
" \"order\": 1,\n" +
" \"Version\": \"v6\"\n" +
" },\n" +
" \"test\": {\n" +
" \"ModuleID\": \"123456\",\n" +
" \"BoxID\": \"a777\",\n" +
" \"Url\": \"https://google.com\"\n" +
"\n" +
" }\n" +
"\n" +
" },\n" +
" {\n" +
" \"data\": {\n" +
" \"status\": true,\n" +
" \"type\": \"B\",\n" +
" \"order\": 1,\n" +
" \"Version\": \"v2\"\n" +
" },\n" +
" \"test\": {\n" +
" \"ModuleID\": \"123456\",\n" +
" \"BoxID\": \"a777\",\n" +
" \"Url\": \"https://google.com\"\n" +
"\n" +
"\n" +
" }\n" +
" }\n" +
"\n" +
"],\n" +
"\"Service2\": {\n" +
" \"data1\": {\n" +
" \"status\": false,\n" +
" \"type\": \"c\",\n" +
" \"order\": 1,\n" +
" \"Version\": \"v6\"\n" +
" },\n" +
" \"dashboard\": {\n" +
" \"ModuleID\": \"123456\",\n" +
" \"BoxID\": \"a777\",\n" +
" \"Url\": \"https://google.com\"\n" +
"\n" +
" }\n" +
"}\n" +
"}";
System.out.println(jsonData);
try {
JSONObject response = new JSONObject(jsonData);//replace json data with your given json data
JSONArray service1 = response.getJSONArray("Service1");
JSONObject firstObjectInService1 = service1.getJSONObject(0);
JSONObject secondObjectInService1 = service1.getJSONObject(1);
JSONObject dataInFirstObject = firstObjectInService1.getJSONObject("data");
JSONObject dataInSecondObject = secondObjectInService1.getJSONObject("data");
System.out.println(dataInFirstObject);
System.out.println(dataInSecondObject);
} catch (JSONException je) {
//do what you want
}
}
}
so finally in dataInFirstObject we have:
{
"status": false,
"type": "A",
"order": 1,
"Version": "v6"
}
and dataInSecondObject we have:
{
"status": true,
"type": "B",
"order": 1,
"Version": "v2"
}
You can use JSON simple library ,it is library used to read/write/parse data in JSON file.In this example i read data from JSON file not a JSON content directly.
private void findData() {
ArrayList<String> dataArrayList=new ArrayList<>();
try {
JSONParser parser = new JSONParser();
InputStream in = getClass().getResourceAsStream("/json/Services.json");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
Object obj = parser.parse(reader);
JSONObject jsonObject = (JSONObject) obj;
JSONArray msg = (JSONArray) jsonObject.get("Service1");
Iterator<JSONObject> iterator = msg.iterator();
while (iterator.hasNext()) {
JSONObject jsonObjectData = iterator.next();
JSONObject dataObject = (JSONObject) jsonObjectData.get("data");
System.out.println(dataObject);
//Extract values
dataObject.values().stream().forEach(value->{
System.out.println(value);
dataArrayList.add(value.toString());
});
}
} catch (IOException | org.json.simple.parser.ParseException ex) {
Logger.getLogger(CorporationRegistrationFormController.class.getName()).log(Level.SEVERE, null, ex);
}
}
If you need read JSON content from your code just replace the reader with your content like this : Object obj = parser.parse("JSON content");

Categories