Update elements in a JSONObject - java

Lets say I gave a JSONObject
{
"person":{"name":"Sam", "surname":"ngonma"},
"car":{"make":"toyota", "model":"yaris"}
}
How do I update some of the values in the JSONObject?
Like below :
String name = jsonArray.getJSONObject(0).getJSONObject("person").getString("name");
name = "Sammie";

Use the put method: https://developer.android.com/reference/org/json/JSONObject.html
JSONObject person = jsonArray.getJSONObject(0).getJSONObject("person");
person.put("name", "Sammie");

Remove key and then add again the modified key, value pair as shown below :
JSONObject js = new JSONObject();
js.put("name", "rai");
js.remove("name");
js.put("name", "abc");
I haven't used your example; but conceptually its same.

Hello I can suggest you universal method. use recursion.
public static JSONObject function(JSONObject obj, String keyMain,String valueMain, String newValue) throws Exception {
// We need to know keys of Jsonobject
JSONObject json = new JSONObject()
Iterator iterator = obj.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
// if object is just string we change value in key
if ((obj.optJSONArray(key)==null) && (obj.optJSONObject(key)==null)) {
if ((key.equals(keyMain)) && (obj.get(key).toString().equals(valueMain))) {
// put new value
obj.put(key, newValue);
return obj;
}
}
// if it's jsonobject
if (obj.optJSONObject(key) != null) {
function(obj.getJSONObject(key), keyMain, valueMain, newValue);
}
// if it's jsonarray
if (obj.optJSONArray(key) != null) {
JSONArray jArray = obj.getJSONArray(key);
for (int i=0;i<jArray.length();i++) {
function(jArray.getJSONObject(i), keyMain, valueMain, newValue);
}
}
}
return obj;
}
It should work. If you have questions, go ahead.. I'm ready.

Generic way to update the any JSONObjet with new values.
private static void updateJsonValues(JsonObject jsonObj) {
for (Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) {
JsonElement element = entry.getValue();
if (element.isJsonArray()) {
parseJsonArray(element.getAsJsonArray());
} else if (element.isJsonObject()) {
updateJsonValues(element.getAsJsonObject());
} else if (element.isJsonPrimitive()) {
jsonObj.addProperty(entry.getKey(), "<provide new value>");
}
}
}
private static void parseJsonArray(JsonArray asJsonArray) {
for (int index = 0; index < asJsonArray.size(); index++) {
JsonElement element = asJsonArray.get(index);
if (element.isJsonArray()) {
parseJsonArray(element.getAsJsonArray());
} else if (element.isJsonObject()) {
updateJsonValues(element.getAsJsonObject());
}
}
}

public static JSONObject updateJson(JSONObject obj, String keyString, String newValue) throws Exception {
JSONObject json = new JSONObject();
// get the keys of json object
Iterator iterator = obj.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
// if the key is a string, then update the value
if ((obj.optJSONArray(key) == null) && (obj.optJSONObject(key) == null)) {
if ((key.equals(keyString))) {
// put new value
obj.put(key, newValue);
return obj;
}
}
// if it's jsonobject
if (obj.optJSONObject(key) != null) {
updateJson(obj.getJSONObject(key), keyString, newValue);
}
// if it's jsonarray
if (obj.optJSONArray(key) != null) {
JSONArray jArray = obj.getJSONArray(key);
for (int i = 0; i < jArray.length(); i++) {
updateJson(jArray.getJSONObject(i), keyString, newValue);
}
}
}
return obj;
}

Recursive way to update value in depth in Kotlin
Example: setJsonValue("obj1/obj2/keyToUpdate", "new value")
fun setJsonValue(path: String, value: Any?) {
setJsonValueRec(
path = path.split("/"),
index = 0,
obj = jsonObj,
value = value
)
}
private fun setJsonValueRec(path: List<String>, index: Int, obj: JSONObject, value: Any?): JSONObject {
return obj.put(
path[index],
when (index) {
path.lastIndex -> value
else -> setJsonValueRec(
path = path,
index = index + 1,
obj = obj.getJSONObject(path[index]),
value = value
)
}
)
}

Related

Read hashmap nested properties dynamically

I have the JSON below:
"total":"2",
"offset":"1",
"limit":"2",
"results":[{
"code":1,
"title":"RESTAURANTE SADOCHE",
"contact":{
"code":10,
"name":"HENRIQUE BARBALHO",
"company":{
"code":100,
"name":"RESTAURANTE SADOCHE LTDA-ME"
}
}
},
{
"code":2,
"title":"ARNALDO GRILL",
"contact":{
"code":20,
"name":"FÁTIMA COSTA",
"company":{
"code":200,
"name":"COSTA NATAL RESTAURANTE EIRELI"
}
}
}]
I turned this JSON into a Java HashMap using the Gson library.
Map<String, Object> retMap = new Gson().fromJson(jsonUpString, new TypeToken<HashMap<String, Object>>(){}.getType());
I need to dynamically read some properties of this created hashmap. Ex: title, name of contact and name of company.
Sometimes these properties (title, name of contact and name of company) can be inside lists.
Below my code:
String propertyName = "name";
String nesting = "results;contact;company";
String[] levels = nesting.split(";");
Map map = new HashMap();
map = retMap;
for (int i = 0; i < niveis.length; i++) {
map = (Map)map.get(levels[i]);
System.out.println(map);
if (i == levels.length - 1) {
System.out.println(map.get(propertyName));
}
}
But if the properties (results, contact or company) return more than one object, the JSON returns them as lists, and I can't get the information I need.
I solved the problem using...
private static void leJSON(Object object) {
if (object instanceof JSONObject) {
Set < String > ks = ((JSONObject) object).keySet();
for (String key: ks) {
Object value = ((JSONObject) object).get(key);
if (value != null) {
System.out.printf("%s=%s (%s)\n", key, value, value.getClass().getSimpleName());
if (value.getClass().getSimpleName().equalsIgnoreCase("JSONArray")) {
JSONArray ja = (JSONArray) value;
for (int i = 0; i < ja.size(); i++) {
leJSON(ja.get(i));
}
}
if (value.getClass().getSimpleName().equalsIgnoreCase("JSONObject")) {
leJSON(value);
}
}
}
}
}
main method...
String json = "{...}";
JSONObject object = (JSONObject) JSONValue.parse(jsonString2);
readJSON(object);

split values while printing in a file

I am printing a value in a file i need to split them onces the first content is finished leave some spaces and then print the next one
public class Test_Json {
public static ArrayList<Object> ls1 = new ArrayList<Object>();
public static ArrayList<Object> ls2 = new ArrayList<Object>();
public static void main(String[] args) throws Exception {
JsonParser parser = new JsonParser();
BufferedWriter bw = null;
FileWriter fw = null;
try {
Gson g = new Gson();
JsonElement jsonElement1 = parser.parse(new FileReader("D://sample1.json"));
JsonElement jsonElement2 = parser.parse(new FileReader("D://sample2.json"));
// System.out.println("Is the two JSON File Same: "+compareJson(jsonElement1,jsonElement2));
if (!compareJson(jsonElement1, jsonElement2)) {
Type mapType = new TypeToken<Map<String, Object>>() {
}.getType();
Map<String, Object> firstMap = g
.fromJson(jsonElement1, mapType);
Map<String, Object> secondMap = g.fromJson(jsonElement2,
mapType);
System.out.println(" The Two JSON Files Are Not the Same ");
System.out.println(Maps.difference(firstMap, secondMap));
String s = Maps.difference(firstMap, secondMap).toString();
try{
fw = new FileWriter("D:\\output.txt");
bw = new BufferedWriter(fw);
bw.write(s);
}catch(Exception e){
e.printStackTrace();
}
} else {
System.out.println("The Two JSON Are SAME!!!!!!!!!!!!!!!");
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
public static boolean compareJson(JsonElement json1, JsonElement json2) {
boolean isEqual = true;
if (json1 != null && json2 != null) {
if (json1.isJsonObject() && json2.isJsonObject()) {
Set<Entry<String, JsonElement>> ens1 = ((JsonObject) json1)
.entrySet();
Set<Entry<String, JsonElement>> ens2 = ((JsonObject) json2)
.entrySet();
JsonObject json2obj = (JsonObject) json2;
if (ens1 != null && ens2 != null
&& (ens2.size() == ens1.size())) {
for (Entry<String, JsonElement> en : ens1) {
isEqual = isEqual
&& compareJson(en.getValue(),
json2obj.get(en.getKey()));
}
} else {
return false;
}
}
else if (json1.isJsonArray() && json2.isJsonArray()) {
JsonArray jarr1 = json1.getAsJsonArray();
JsonArray jarr2 = json2.getAsJsonArray();
if (jarr1.size() != jarr2.size()) {
return false;
} else {
int i = 0;
for (JsonElement je : jarr1) {
isEqual = isEqual && compareJson(je, jarr2.get(i));
i++;
}
if (isEqual) {
ls1.toArray();
ls2.toArray();
isEqual = ls1.containsAll(ls2);
}
}
}
else if (json1.isJsonNull() && json2.isJsonNull()) {
return true;
}
else if (json1.isJsonPrimitive() && json2.isJsonPrimitive()) {
ls1.add(json1);
ls2.add(json2);
return true;
}
else if((json1.isJsonPrimitive() & json2.isJsonArray()) || (json2.isJsonPrimitive() && json1.isJsonArray())){
return false;
}
} else if (json1 == null && json2 == null) {
return true;
} else {
return false;
}
return isEqual;
}
}
Map.difference method gets the difference form the two file and prints them. I need to first print first file difference and then leave some lines of space and print the next file difference. This i am doing to show the contents seperately. At present it is displaying without any spaces so identifying is difficult.
I need something like this
Difference values in first file:
{
"id": 1,
"name": "A green door",
"price": 12.50,
"tags": ["home", "green"]
}
Difference in second file:
{
"id": 14,
"name": "A green door bell",
"price": 127.50,
"tags": ["home", "green"]
}
The method entriesOnlyOnLeft() and entriesOnlyOnRight() is not displaying the differece as the key should be different but here the key are same
If you want to print the map differences with a separation between the left and right sides, you can get them separately from the MapDifference result:
MapDifference diff = Maps.difference(firstMap, secondMap);
bw.write("Only on left: " + diff.entriesOnlyOnLeft());
// add separation
bw.write("Only on right: " + diff.entriesOnlyOnRight());
To include the value differences:
bw.write("Value differences: " + diff.entriesDiffering());

How to get keys in nested json with parent prefix using GSON in java

I have tried the following example.
public static void operate2(JsonElement jsonElement, List keys, JsonElement jsonElement2, String prefix){
String prefixnew = "";
if(jsonElement.isJsonArray()){
JsonArray jsonArray = jsonElement.getAsJsonArray();
for(int i=0; i<jsonArray.size(); i++){
jsonElement = jsonArray.get(i);
operate2(jsonElement, keys, jsonElement2, prefix);
}
}else if(jsonElement.isJsonObject()){
JsonObject jsonObject = jsonElement.getAsJsonObject();
Set<Map.Entry<String,JsonElement>> childEntrySet = jsonObject.entrySet();
for (Map.Entry<String, JsonElement> child: childEntrySet) {
jsonElement2 = child.getValue();
Object keyCheck = new Gson().fromJson(jsonElement2.toString(), Object.class);
if (keyCheck instanceof Map) {
prefix += child.getKey()+"_";
keys.add(prefix);
System.out.println("Map="+child.getKey());
}else if (keyCheck instanceof Collection) {
if(!prefix.equals("")){
prefix += child.getKey()+"_";
keys.add(prefix);
}else{
prefix = child.getKey()+"_";
keys.add(prefix);
}
System.out.println("Collection="+child.getKey());
}else{
prefix += "";
}
operate2(jsonElement2, keys, jsonElement2, prefix);
}
}else{
prefix = "";
}
}
public static void test2(String json){
JsonElement jsonElement = new JsonParser().parse(json);
JsonElement jsonElement2 = null;
String prefix = "";
List keys = new ArrayList();
operate2(jsonElement, keys, jsonElement2, prefix);
Set keySet = new HashSet(keys);
System.out.println("Keys = "+keys);
}
The output I got Keys = [items_, items_contact_, items_contact_records_, items_contact_records_recordings_, items_contact2_]
But I need items_, items_contact_, items_records_ .... As we can see that record is not the child of the contact, so items_contact_records_ should not be there. Instead items_records_ should be.
The source json would be
{
"items": [{
"id": 633706061003,
"fromNumber": "16572307534",
"contact": {
"id": 499354453003,
"homePhone": "16572307534"
},
"records": [{
"id": 353389055003,
"result": "LA",
"recordings": [{
"id": 16427622003
}]
}]
}],
"limit": 100,
"offset": 0,
"totalCount": 5949
}
I would use the following approach:
if the root element is not a json object, return an empty list
otherwise iterate other its entries, and for each one add the key if the value associated with is either an object or an array
proceed recursively for the value
public static List<String> operate(final JsonElement jsonElement, final String prefix, final boolean firstLayer) {
if(jsonElement.isJsonObject() || (!firstLayer && jsonElement.isJsonArray())) {
List<String> keys = new ArrayList<>();
if(jsonElement.isJsonObject()) {
JsonObject jObj = jsonElement.getAsJsonObject();
for(Map.Entry<String, JsonElement> entry : jObj.entrySet()) {
JsonElement value = entry.getValue();
String newPrefix = prefix + entry.getKey();
if(value.isJsonArray() || value.isJsonObject()) {
keys.add(newPrefix);
keys.addAll(operate(value, newPrefix + "_", false));
}
}
} else {
JsonArray array = jsonElement.getAsJsonArray();
for(JsonElement element : array) {
keys.addAll(operate(element, prefix, false));
}
}
return keys;
} else {
return Collections.emptyList();
}
}
and the test method:
public static void test(String json) {
JsonElement jsonElement = new JsonParser().parse(json);
List<String> keys = operate(jsonElement, "", true);
System.out.println("Keys = " + keys);
}
Running it on your example, you'll get:
Keys = [items, items_contact, items_records, items_records_recordings]

Access first array in a JSON string using JSON Parser

How do I access the array products from the below JSON string? I would ideally do this, and it works -
JSONParser parser = new JSONParser();
Object response = parser.parse(json);
JSONObject jsonObject = (JSONObject) response;
JSONObject info = (JSONObject) jsonObject.get("info");
JSONArray data = (JSONArray) jsonObject.get("products");
But the problem is the root element info is not always the same, so I can't hardcode my code. Basically, I don't want to access products by accessing info first. I want to directly access the products array.
How can I do this?
{
"info": {
"products": [
{
"test": 11577,
"number": 2541,
"product": "deoderant",
"id": 1,
"subId": 5,
"tempId": 3,
"name": null,
"lastModified": "2015-05-24",
"lastUsed": 5,
"score": 0.93,
"season": "Seasonal",
"availability": 0,
"itemRanking": null,
"itemQuantity": 5,
"listOfStores": [
7896
]
}
],
"storeId": 10145678
}
}
convert to map, LinkedHashMap or HashMap as per your need, then get the entry value.
public class Test {
public static void main(String[] args) {
String json = "{\"info\": {\"products\": [{\"test\": 11577,\"number\": 2541,\"product\": \"deoderant\",\"id\": 1,\"subId\": 5,\"tempId\": 3,\"name\": null,\"lastModified\": \"2015-05-24\",\"lastUsed\": 5,\"score\": 0.93,\"season\": \"Seasonal\",\"availability\": 0,\"itemRanking\": null,\"itemQuantity\": 5,\"listOfStores\": [7896]}],\"storeId\": 10145678}}";
JSONObject jsonObject;
try {
jsonObject = new JSONObject(json);
Map<String, Object> map = getMap(jsonObject);
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static Map getMap(JSONObject object) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
Object jsonObject = null;
String key = null;
Object value = null;
try {
Iterator<String> keys = object.keys();
while (keys.hasNext()) {
key = null;
value = null;
key = keys.next();
if (null != key && !object.isNull(key)) {
value = object.get(key);
}
if (value instanceof JSONObject) {
map.put(key, getMap((JSONObject) value));
continue;
}
if (value instanceof JSONArray) {
JSONArray array = ((JSONArray) value);
List list = new ArrayList();
for (int i = 0 ; i < array.length() ; i++) {
jsonObject = array.get(i);
if (jsonObject instanceof JSONObject) {
list.add(getMap((JSONObject) jsonObject));
} else {
list.add(jsonObject);
}
}
map.put(key, list);
continue;
}
map.put(key, value);
}
} catch (Exception e) {
System.out.println(e);
}
return map;
}
}
Output
info
{products=[{test=11577, number=2541, product=deoderant, id=1, subId=5, tempId=3, name=null, lastModified=2015-05-24, lastUsed=5, score=0.93, season=Seasonal, availability=0, itemRanking=null, itemQuantity=5, listOfStores=[7896]}], storeId=10145678}
I don't know if this is the best way - but you can always get the keys of your objects with the keys() method. So you will know the name of the top object.
Use fasterxml lib,you can write code like below:
ObjectMapper mapper = new ObjectMapper();
// json is your json string
String json = "";
JsonNode jsonNode = node.findParent("products").get("products");
System.out.println(jsonNode);

Get the json path of a value with jackson

I'm trying to retrieve the json path of a value from a json string with jackson. As I couldn't find any function inside jackson giving me this result, I wanted to create my own function.
So I made this function :
public static String getJsonPath(Map.Entry<String, JsonNode> jsonNode, String valueSearched) {
String res = "";
String key = jsonNode.getKey();
JsonNode value = jsonNode.getValue();
if (value.isValueNode() && value.equals(valueSearched)) { // Here the value change to a ValueNode and the key weirdly equals to "".
return res + key;
} else {
if (value.isContainerNode()) {
if (value.isObject()) {
Iterator<Map.Entry<String, JsonNode>> elements = value.fields();
while (elements.hasNext()) {
Map.Entry<String, JsonNode> element = elements.next();
res += "." + element.getKey() + generateJsonPathArgumentFromJson(element, valueSearched);
}
} else {
int i = 0;
ArrayNode arrayNode = (ArrayNode) jsonNode;
Iterator<Map.Entry<String,JsonNode>> elements = arrayNode.fields();
while (elements.hasNext()) {
Map.Entry<String, JsonNode> element = elements.next();
i++;
res += "(" + i + ")" + generateJsonPathArgumentFromJson(element, valueSearched);
}
}
}
}
return "";
}
Why the key gets equal to "" after the first if ? Or there's a better way to construct a json path for a specific value ?
Just get the solutions :
protected static String generateJsonPathArgumentFromJson(JsonNode jsonNode, String valueSearched) {
if (jsonNode.isValueNode() && !jsonNode.asText().equals(valueSearched)) {
return null;
} else {
if (jsonNode.isContainerNode()) {
if (jsonNode.isObject()) {
Iterator<Map.Entry<String, JsonNode>> elements = jsonNode.fields();
while (elements.hasNext()) {
Map.Entry<String, JsonNode> element = elements.next();
String res = generateJsonPathArgumentFromJson(element.getValue(), valueSearched);
if (res != null) {
return "." + element.getKey() + res;
}
}
} else {
int i = 0;
Iterator<JsonNode> elements = jsonNode.elements();
while (elements.hasNext()) {
JsonNode element = elements.next();
String res = generateJsonPathArgumentFromJson(element, valueSearched);
if (res != null) {
return "(" + i + ")" + res;
}
i++;
}
}
}
}
return "";
}
I'm sure there's better way to do, but at least it works :)

Categories

Resources