23

here is the json file

{
    "session":
        {
            "name":"JSESSIONID",
            "value":"5864FD56A1F84D5B0233E641B5D63B52"
        },
    "loginInfo":
        {
            "loginCount":77,
            "previousLoginTime":"2014-12-02T11:11:58.561+0530"
        }
}

I want to change the value of name.by directly giving XPath/JsonPath Like

($.session.name).changevalue("MYSESSINID") this is just a Example

I am correctly using jackson library and using the below code for reading via XPath

ObjectMapper mapper = new ObjectMapper();

        Object jsonObj=mapper.readValue(new File(Json file), Object.class);
        Object name=PropertyUtils.getProperty(jsonObj, "session.name");
        System.out.println("Name:"+name);

so is their a way to change the name by XPath

PropertyUtils.setProperty(jsonObj, "session.value", "new value");

still in the file its not working.

Rao
  • 20,781
  • 11
  • 57
  • 77
vaibhavcool20
  • 861
  • 3
  • 11
  • 28
  • PropertyUtils has a setProperty method as well, have you tried that? – flup Dec 02 '14 at 08:03
  • @flup setProperty code is not working its not giving any error but its not changing the value either – vaibhavcool20 Dec 02 '14 at 08:56
  • The object tree lives in memory only. So after you change the value in the object tree, you have to serialize it back to file. – flup Dec 02 '14 at 09:01
  • @flup
    PropertyUtils.setProperty(jsonObj, "session.name", "lkihilh"); mapper.writeValue(json file ,jsonObj); this will write the entire json code in a file if the file is big it consume a lot of time Is their in other way to do it
    – vaibhavcool20 Dec 02 '14 at 09:48
  • If the file is big, reading it into memory will take a lot of memory and writing it will take a lot of time. Such is the way of things ;) Is this your actual question then? How to edit JSON files in a streaming way, or even in place on the harddisk? Or merely how to do this using Jackson and PropertyUtils? – flup Dec 02 '14 at 10:46
  • @flup initially that was my question now my question is there a way to edit json file without re writing the entire file. so that it can be more code be efficient. – vaibhavcool20 Dec 03 '14 at 08:38
  • 1
    Probably best to create a new question for the new question :) – flup Dec 03 '14 at 14:45

4 Answers4

47

Using Jayways JsonPath you can:

private static final Configuration configuration = Configuration.builder()
    .jsonProvider(new JacksonJsonNodeJsonProvider())
    .mappingProvider(new JacksonMappingProvider())
    .build();

@Test
public void a_value_can_be_updated(){

    String originalJson = "{\n"
        + "\"session\":\n"
        + "    {\n"
        + "        \"name\":\"JSESSIONID\",\n"
        + "        \"value\":\"5864FD56A1F84D5B0233E641B5D63B52\"\n"
        + "    },\n"
        + "\"loginInfo\":\n"
        + "    {\n"
        + "        \"loginCount\":77,\n"
        + "        \"previousLoginTime\":\"2014-12-02T11:11:58.561+0530\"\n"
        + "    }\n"
        + "}";

    JsonNode updatedJson = JsonPath.using(configuration).parse(originalJson).set("$.session.name", "MYSESSINID").json();

    System.out.println(updatedJson.toString());
}

You can configure the default JsonProvider so you don't have to pass it in all calls.

kalle
  • 1,869
  • 14
  • 14
  • I tried your solution but it is setting a number value as string. Any solution to this? eg : tried to set login count to 1, it was returned as : "loginCount":"1" – InCh Dec 28 '16 at 10:52
  • Oh found the solution! Pass integer object to set as int – InCh Dec 28 '16 at 11:10
  • 1
    What if multiple nodes are matched? Looks like there's a need for something like "forEach" with custom handler that could handle nodes of any types. – mvmn Apr 25 '18 at 13:53
  • 1
    Note that this only works if the specified key already exists. – RedShift Oct 28 '19 at 12:56
3
PropertyUtils.setProperty(jsonObj, "session.value", "new value");
        PropertyUtils.setProperty(jsonObj, "session.name", "new name");
        mapper.writeValue(Json File ,jsonObj);
vaibhavcool20
  • 861
  • 3
  • 11
  • 28
3

the easiest way i found to exchange inside Json (When my Body is a JSONObject)

import com.jayway.jsonpath.JsonPath;


JsonPath.parse(Body).set(fieldPath, Value);
Vladi
  • 1,662
  • 19
  • 30
0

I tried Kalle's way, it always said jsonPath not found when I am adding a new field.

So I used this updated way to add a new field

        @Test
        public void a_node_can_be_updated_and_created() throws ParseException{
        
        System.out.println(originalJson);
        JSONObject json = (JSONObject)new JSONParser(JSONParser.DEFAULT_PERMISSIVE_MODE).parse(originalJson);
        JSONObject session = JsonPath.read(json, "$.session");
        session.appendField("new__field", "new__value");        // add a new field
        session.put("name", "Justin2");                         // update an existing field
        System.out.println(JsonFormatter.prettyPrint(json.toJSONString()) );
        
    }

This new way also doesn't need Jackson library, only Jayway.

Justin
  • 1,050
  • 11
  • 26