How to rewrite full updated json instead of only the nested part - java

I have a json file called test.json that looks like:
{
"Added": {
"type": "K",
"newmem": {
"IDNew": {
"id": "777709",
"type": "LOP"
},
"birthDate": "2000-12-09"
},
"code": "",
"newest": {
"curlNew": "",
"addedForNew": ""
}
}
}
I am able to update the id in the json and write back to the file using the following code:
FileReader reader = new FileReader(filePath); //where file path = D://.../test.json
String keyToUpdate = "Added.newmem.IDNew.id"
String[] keyArr = jsonKey.split("\\." );
String keyToUpdate = keyArr [keyArr.length-1]
keyArr.removeElement(keyArr, keyToUpdate)
for (String key: keyArr){
jsonObject = (JSONObject) jsonObject.get(key);
}
jsonObject.put("id",12345);
FileOutputStream outputStream = new FileOutputStream(filePath);
byte[] strToBytes = jsonObject.toString().getBytes();
outputStream.write(strToBytes);
However, instead of re-writing the entire json with the updated value, it's only writing:
{
"id": "777709",
"type": "LOP"
}
What can I do to re-write the entire json instead of only the nested part of it?

Your jsonObject before update only contains the "IDNew" node.
The best way to do this is using xPath from Jayway
private static final Configuration configuration = Configuration.builder()
.jsonProvider(new JacksonJsonNodeJsonProvider())
.mappingProvider(new JacksonMappingProvider())
.build();
String originalJson = "{\r\n"
+ " \"Added\": {\r\n"
+ " \"type\": \"K\",\r\n"
+ " \"newmem\": {\r\n"
+ " \"IDNew\": {\r\n"
+ " \"id\": \"777709\",\r\n"
+ " \"type\": \"LOP\"\r\n"
+ " },\r\n"
+ " \"birthDate\": \"2000-12-09\"\r\n"
+ " },\r\n"
+ " \"code\": \"\",\r\n"
+ " \"newest\": {\r\n"
+ " \"curlNew\": \"\",\r\n"
+ " \"addedForNew\": \"\"\r\n"
+ " }\r\n"
+ " }\r\n"
+ "}";
JsonNode updatedJson = JsonPath.using(configuration).parse(originalJson).set("$.Added.IDNew.id", 12345).json();
System.out.println(updatedJson.toString());
}

Related

How to get all key and values from nested JSON in java

Hi I need to read all key, values from nested JSON, where ever there is inner JSON. I need that values ignoring the key.From below JSON i need Key values for nested JSON, like: responseStatus-passed, "statusCode":"200", "retrieveQuoteResponse":null,"quoteGuid":null, etc.ignoring the start key value like: responsePreamble, quoteProductList which has a nested json inside it.
{
"responsePreamble": {
"responseStatus": "Passed",
"statusCode": "200",
"responseMessage": "Records Found"
},
"retrieveQuoteResponse": null,
"totalQuoteProductCount": 2,
"quoteProductList": {
"quoteGuid": null,
"quantity": 180
}
Code:
ObjectReader reader = new ObjectMapper().readerFor(Map.class);
Map<String, Map<String, String>> employeeMap = reader.readValue(jsonObject);
for (Entry<String, Map<String, String>> empMap : employeeMap.entrySet()) {
Map<String, String> addMap = empMap.getValue();
if(addMap!=null) {
for (Entry<String, String> addressSet : addMap.entrySet()) {
System.out.println(addressSet.getKey() + " :: " + addressSet.getValue());
}
}
}
OutPut:
responseStatus :: Passed
statusCode :: 200
responseMessage :: Records Found
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
at com.im.api.tests.CompareTwoJsons.main(CompareTwoJsons.java:78)
For your specific case, the following code will do the job:
String json = "{\n" +
" \"responsePreamble\":{\n" +
" \"responseStatus\":\"Passed\",\n" +
" \"statusCode\":\"200\",\n" +
" \"responseMessage\":\"Records Found\",\n" +
" \"accountInfo\":{\n" +
" \"id\":\"631b3d5b-62c8-e711-80f3-3863bb343ba0\"\n" +
" },\n" +
" \"account\":\"40114570\",\n" +
" \"contactInfo\":{\n" +
" \"id\":\"1af63ebb-2680-eb11-a812-000d3a4e381d\"\n" +
" },\n" +
" \"contact\":\"Kenny Tokuda\",\n" +
" \"currencyInfo\":{\n" +
" \"id\":\"8c2ef-\",\n" +
" \"symbol\":\"$\"\n" +
" },\n" +
" \"vendorCurrencyInfo\":{\n" +
" \"id\":null\n" +
" }\n" +
" },\n" +
" \"retrieveQuoteResponse\":null,\n" +
" \"totalQuoteProductCount\":2,\n" +
" \"quoteProductList\":{\n" +
" \"quoteGuid\":null,\n" +
" \"quantity\":180\n" +
" }\n" +
"}";
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(json);
Iterator<String> iterator = jsonNode.fieldNames();
while (iterator.hasNext()) {
String key = iterator.next();
printRec(jsonNode, key);
}
Here is how function printRec looks like:
public static void printRec(JsonNode jsonNode, String key) {
JsonNode node = jsonNode.get(key);
if (node.isObject()) {
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
fields.forEachRemaining(field -> {
printRec(node, field.getKey());
if (!field.getValue().isObject()) {
System.out.println(field.getKey() + " : " + field.getValue());
}
});
}
}
When you run this code you should see the following output:
responseStatus : "Passed"
statusCode : "200"
responseMessage : "Records Found"
id : "631b3d5b-62c8-e711-80f3-3863bb343ba0"
account : "40114570"
id : "1af63ebb-2680-eb11-a812-000d3a4e381d"
contact : "Kenny Tokuda"
id : "8c2ef-"
symbol : "$"
id : null
quoteGuid : null
quantity : 180

Iterate through a Json object and store some values in an array

I retrieved the following JSON-object. These json array consists of posts. As can be seen from the below, each post has a userId, id, title and a body. Now I need to iterate through this json and get the id of the posts IF the userId is 5 (in this case all four id's will be stored because in all of them the userId is 5
[
{
"userId": 5,
"id": 21,
"title": "A title",
"body": "A body"
},
{
"userId": 5,
"id": 52,
"title": "B title",
"body": "B body"
},
{
"userId": 5,
"id": 13,
"title": "C title",
"body": "C body"
},
{
"userId": 5,
"id": 44,
"title": "D title",
"body": "D body"
},
]
and then I need to store the id values in an array like this:
postIds = [21, 52, 13, 44]
So far I have done this
GetPosts[] getPosts = getPostResponse.as(GetPosts[].class);
String[] userPostIds;
for (int i = 0; i < getPosts.length; i++) {
if(getPosts[0].getId().equals(userId)) {
}
}
Then I tried to write a for loop like this but I know it is wrong. Maybe the statement in if parentheses is true, but for loop needs to be something else and I need to write something inside the if statement but I cannot progress here.
Edit: I now modified the for/if loop like this:
for (int i = 0; i < getPosts.length; i++) {
Integer userPostIds = null;
if (getPosts[i].getId().equals(userId)) {
userPostIds = getPosts.getId();
}
System.out.println(userPostIds);
}
But this time userPostIds is printed like this:
null
null
null
null
whereas I was expecting it to be:
21
52
13
44
Let's assume that you have stored your JSON as a String. You can use Jackson object mapper to map JSON to Object.
private static String JSON = "[\n" +
" {\n" +
" \"userId\": 5,\n" +
" \"id\": 21,\n" +
" \"title\": \"A title\",\n" +
" \"body\": \"A body\"\n" +
" },\n" +
" {\n" +
" \"userId\": 5,\n" +
" \"id\": 52,\n" +
" \"title\": \"B title\",\n" +
" \"body\": \"B body\"\n" +
" },\n" +
" {\n" +
" \"userId\": 5,\n" +
" \"id\": 13,\n" +
" \"title\": \"C title\",\n" +
" \"body\": \"C body\"\n" +
" },\n" +
" {\n" +
" \"userId\": 5,\n" +
" \"id\": 44,\n" +
" \"title\": \"D title\",\n" +
" \"body\": \"D body\"\n" +
" }\n" +
"]";
You need to create object for mapping:
public class Foo {
private Integer userId;
private Integer id;
private String title;
private String body;
// getters
// setters
}
Then you can map your JSON to list of objects:
private static List<Foo> mapJsonToObject() {
var om = new ObjectMapper();
List<Foo> list = null;
try {
list = Arrays.asList(om.readValue(JSON, Foo[].class));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return list;
}
In the end you need to iterate through this list to get all ids.
public static void main(String[] args) {
var list = mapJsonToObject();
var ids = list.stream().map(Foo::getId).collect(Collectors.toList());
System.out.println(ids.toString());
}
Thankfully, the hard part (deserialization) is complete per the OP.
Therefore, to iterate over the object list, I recommend something similar to the following, presuming that the post.getId returns a String (Otherwise, you may need to do a cast conversion)
Log.info("Store all the posts of the user");
GetPosts[] getPosts = getPostResponse.as(GetPosts[].class);
ArrayList<Integer> userIdsFromPosts = new ArrayList<Integer>();
if(getPosts != null) { // Avoiding a Possible NPE in list iteration...Just in case ;)
for (GetPosts post : getPosts) {
Integer currentUserId = post.getId();
if (!userIdsFromPosts.contains(currentUserId)) {
userIdsFromPosts.add(currentUserId);
}
}
}
return userIdsFromPosts;
One final note, if you are expecting a VERY large number of posts, then you should use a HashSet instead of ArrayList for performance reasons (when we run the .contains() method, each element of the ArrayList is iterated over).

I have json object with contain a list of other object and want to convert it in HashMap in java

this is the json , I wanted to convert to HashMap
`
ob = "{
"arrival": "RONGO",
"segmentPrices": [
{
"id": "",
"localId": "",
"localCode": "",
"localDesignation": "",
"amounts": [
{
"value": 950,
"currency": "Ksh"
}
]
}
]
} ";
Gson gson = new Gson();
HashMap<String,Object> result = new ObjectMapper().readValue(gson.toJson(ob), HashMap.class);
`
but i can't access to amounts object,
the value of result.get("amounts") is null
somebody can please help me for this ?
Using gson 2.0 here is what you can parse your json as HashMap and access amounts array:
public static void main(String[] args) throws IOException {
Gson gson = new Gson();
HashMap<String, Object> map = gson.fromJson(new FileReader("test.json"), HashMap.class);
ArrayList<Object> prices = (ArrayList<Object>) map.get("segmentPrices");
prices.forEach(p -> {
if (p instanceof LinkedHashMap) {
System.out.println(((LinkedHashMap)p).get("amounts"));
}
});
}
test.json file contains your json.
Output is:
[{value=950.0, currency=Ksh}]
You can access the parameters inside the object in the amount array as below:
public static void main(String[] args) throws IOException {
Gson gson = new Gson();
HashMap<String, Object> map = gson.fromJson(new FileReader("test.json"), HashMap.class);
ArrayList<Object> prices = (ArrayList<Object>) map.get("segmentPrices");
prices.forEach(p -> {
if (p instanceof LinkedHashMap) {
ArrayList<Object> amounts = (ArrayList<Object>) (((LinkedHashMap)p).get("amounts"));
amounts.forEach(amount -> {
System.out.println(((HashMap<String,Object>)amount).get("value"));
});
}
});
}
output is :
950.0
you will need the java-son library, if you need to extract the value of value this is how you can do it.
String ob = "{\n"
+ " \"arrival\": \"RONGO\",\n"
+ " \"segmentPrices\": [\n"
+ " {\n"
+ " \"id\": \"\",\n"
+ " \"localId\": \"\",\n"
+ " \"localCode\": \"\",\n"
+ " \"localDesignation\": \"\",\n"
+ " \"amounts\": [\n"
+ " {\n"
+ " \"value\": 950,\n"
+ " \"currency\": \"Ksh\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " } ";
JSONObject json = new JSONObject(ob.toString());
System.out.println(json.getJSONArray("segmentPrices").getJSONObject(0).getJSONArray("amounts").getJSONObject(0).get("value"));

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");

Extracting data from JSON and modifying data

I want to extract jkl object from below JSON string. Also after extraction, I want the backslashes to be removed and extract further with the braces. I followed few questions on StackOverflow but it didn't help much.
{
"abc:def": {
"ghi": {
"jkl": "{\"mno:pqr\":{\"ty\":4,\"\\nsensing_service_name:\\\"Number\\\",\\nsensing_service_id: 20\\n}\\n ]\\n}\"}}",
"st": {
"op": 5,
"org": "q9wr9qrq"
},
"uvw": 1
},
"xyz": false
}
}
I tried below code to display jkl object but it is not working. Please suggest what is wrong in this and how to correct the same
JSONObject json = (JSONObject) JSONSerializer.toJSON(data);
JSONObject aa = json.getJSONObject("abc:def");
JSONObject bb = aa.getJSONObject("ghi");
JSONObject cc = bb.getJSONObject("jkl");
System.out.println(cc);
Hope this will help you:
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
public class TestClass {
public static void main(String[] args) throws Exception {
String jsonString = "{\n" +
" \"abc:def\": {\n" +
" \"ghi\": {\n" +
" \"jkl\": \"{\\\"mno:pqr\\\":{\\\"ty\\\":4,\\\"\\\\nsensing_service_name:\\\\\\\"Number\\\\\\\",\\\\nsensing_service_id: 20\\\\n}\\\\n ]\\\\n}\\\"}}\",\n" +
" \"st\": {\n" +
" \"op\": 5,\n" +
" \"org\": \"q9wr9qrq\"\n" +
" },\n" +
" \"uvw\": 1\n" +
" },\n" +
" \"xyz\": false\n" +
" }\n" +
"} ";
JSONObject jsonObject = new JSONObject(jsonString);
jsonObject = (JSONObject) jsonObject.get("abc:def");
jsonObject = (JSONObject) jsonObject.get("ghi");
String result = jsonObject.getString("jkl");
result = StringUtils.replace(result, "\\n", "");
System.out.println(result.replaceAll("\\\\",""));
}
}

Categories