You don't need to remove before calling put. JSONObject#put will replace any existing value. Simply call
js.getJSONObject("glossary").getJSONObject("GlossDiv").put("seeds", "555");
But how to get to wanted key for one step?
You don't. You have a nested object tree. You must go through the full tree to reach your element. There might be a library out there that does this for you, but underneath it all, it will be traversing everything.
Answer from Sotirios Delimanolis on Stack OverflowYou don't need to remove before calling put. JSONObject#put will replace any existing value. Simply call
js.getJSONObject("glossary").getJSONObject("GlossDiv").put("seeds", "555");
But how to get to wanted key for one step?
You don't. You have a nested object tree. You must go through the full tree to reach your element. There might be a library out there that does this for you, but underneath it all, it will be traversing everything.
I found solution.
public static JSONObject setProperty(JSONObject js1, String keys, String valueNew) throws JSONException {
String[] keyMain = keys.split("\\.");
for (String keym : keyMain) {
Iterator iterator = js1.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
if ((js1.optJSONArray(key) == null) && (js1.optJSONObject(key) == null)) {
if ((key.equals(keym))) {
js1.put(key, valueNew);
return js1;
}
}
if (js1.optJSONObject(key) != null) {
if ((key.equals(keym))) {
js1 = js1.getJSONObject(key);
break;
}
}
if (js1.optJSONArray(key) != null) {
JSONArray jArray = js1.getJSONArray(key);
for (int i = 0; i < jArray.length(); i++) {
js1 = jArray.getJSONObject(i);
}
break;
}
}
}
return js1;
}
public static void main(String[] args) throws IOException, JSONException {
FileInputStream inFile = new FileInputStream("/home/ermek/Internship/labs/java/task/test5.json");
byte[] str = new byte[inFile.available()];
inFile.read(str);
String text = new String(str);
JSONObject json = new JSONObject(text);
setProperty(json, "rpc_server_type", "555");
System.out.println(json.toString(4));
JsonPath provides a convenient way of addressing nodes in json documents. JayWay is a good java implementation.
With JayWay:
DocumentContext doc = JsonPath.parse(json);
doc.set("level-1.level-2.level-3.level-4b[0].level-4b-3.StartDate", Instant.now().toString());
System.out.println(doc.jsonString());
If you are open to using Google's JSON library (https://github.com/google/gson), you can update nested elements and save them as shown in the following sample code:
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonObject;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
import java.io.FileReader;
import java.nio.file.StandardOpenOption;
public class JsonUpdater {
// Method to update nested json elements
public void updateJson(String inputFile, String outputFile) {
try {
// Get the json content from input file
String content = new String(Files.readAllBytes(Paths.get(inputFile)));
// Get to the nested json object
JsonObject jsonObj = new Gson().fromJson(content, JsonObject.class);
JsonObject nestedJsonObj = jsonObj
.getAsJsonObject("level-1")
.getAsJsonObject("level-2")
.getAsJsonObject("level-3")
.getAsJsonArray("level-4b").get(0).getAsJsonObject();
// Update values
nestedJsonObj.addProperty("level-4b-1", "new-value-4b-1");
nestedJsonObj.getAsJsonObject("level-4b-3").addProperty("StartDate", "newdate");
// Write updated json to output file
Files.write(Paths.get(outputFile), jsonObj.toString().getBytes(), StandardOpenOption.CREATE);
} catch (IOException exception) {
System.out.println(exception.getMessage());
}
}
// Main
public static void main(String[] args) {
JsonUpdater jsonUpdater = new JsonUpdater();
jsonUpdater.updateJson("test.json", "new.json");
}
}
The above code reads json string from test.json, updates the values for level-4b-1 and StartDate (within level-4b-3), and saves the updated json string into new.json.
You can use :
JsonNode data = new ObjectMapper().readTree(dataString);
((ObjectNode) data.get("expiryDate")).put("value", "05-02-2020");
Where :
((ObjectNode) data.get("expiryDate"))you get the parent, and thenput("value", "05-02-2020")change the value of the nested node
Output
{"expiryDate":{"type":"String","value":"05-02-2020"}}
You can user ObjectNode .put and update the existing value below is the tested code
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class Test {
public static void main(String[] args) throws Exception {
String datString = "{ \"expiryDate\" : { \"type\" : \"String\", \"value\" : \"31-12-2019\" } } ";
JsonNode data = new ObjectMapper().readTree(datString);
System.out.println(" before update json"+data);
String expiryDate = data.get("expiryDate").get("value").textValue();
((ObjectNode) data.get("expiryDate")).put("value", "05-02-2020");
System.out.println(" updated json "+data);
} }
You should do it with the spread operator.
A spread operator replicates values and you can explicitly update the ones you want. Like i changed code to 5000
let test = {
"application": "ERP",
"subject": "Quote 0000005 from TestSG",
"exportDocumentRequest": {
"documentDate": "05-02-2020",
"tenantBillingAddr": null,
"code": "0000"
}
}
let updated_test = {
...test,
"exportDocumentRequest": {
...test.exportDocumentRequest,
"code": "5000"
}
}
console.log(updated_test)
Duplicate of How to edit, modify nested JSONObject
Following worked for me.
requestParams.getJSONObject("exportDocumentRequest").put("code", "1234");
I didn't completely understand what do you mean but if you want to load nested resources 'eagerly' in SDR, you can turn off exporting of related 'nested' repos (or even completely remove them). For example:
@Entity
public class Parent {
//...
@OneToMany(cascaded = ALL, orphanRemoval = true)
private Set<Child> children;
}
@Entity
public class Child {
//...
}
@RepositoryRestResource
public interface ParentRepo extends JpaRepository<Parent, Long> {}
@RepositoryRestResource(exported = false)
public interface ChildRepo extends JpaRepository<Child, Long> {}
Also you can add cascade = ALL, orphanRemoval = true parameters to OneToMany annotation.
Then all your child objects will be managed by Parent object, and the common payload will be looks like this:
{
"name": "parent1",
"children": [
{
"name": "child1"
},
{
"name": "child2"
}
]
}
Sounds as a good place for graphql.com
It allows to get all of the data you need, in one request. You can define API and call queries requesting only necessary part of data.
It supports customized updates as well.