Reputation: 1152
I am using com.fasterxml.jackson.databind.JsonNode
java library to parse a JSON
and perform some manipulation on the JSON
string as follows -
public static void main(String[] args) {
{
String jsonString = "{\"state\":{\"reported\":{\"deviceParams\":{\"deviceStatus\":{\"solenoid\":10,\"airFlow\":20}}}}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = null;
try {
jsonNode = mapper.readTree(jsonString);
} catch (IOException e) {
e.printStackTrace();
}
JsonNode subNode = jsonNode.get("state").get("reported").get("deviceParams").get("deviceStatus");
//Now subNode = {"solenoid":10,"airFlow":20}
modifySubNode((ObjectNode) subNode);
//type-casting JsonNode to ObjectNode since JSON manipulation like deletion and addition of nodes is only allowed in ObjectNode, not JsonNode
}
private static void modifySubNode(ObjectNode node) {
if (node.get("solenoid") != null) {
node.put("solenoid", 100);
}
}
After the function call modifySubNode()
, I expected the value of jsonNode
to remain as
{
"state":
{
"reported":
{
"deviceParams":
{
"deviceStatus":
{
"solenoid": 10,
"airFlow": 20
}
}
}
}
}
But instead, it became this
{
"state":
{
"reported":
{
"deviceParams":
{
"deviceStatus":
{
"solenoid": 100,
"airFlow": 20
}
}
}
}
}
Why is this happening ? I thought that any changes to "subNode" should not reflect on "jsonNode
". Is there a mis-understanding on my part ?
Upvotes: 0
Views: 665
Reputation: 140553
Here:
jsonNode = mapper.readTree(deviceShadow);
That creates an in memory representation of your JSON data. Simply some sort of data structure that reflects the structure and content of your JSON string.
This here:
JsonNode subNode = jsonNode.get(...
then traverses that in-memory structure and identifies a sub-structure of it. Then you modify that substructure:
node.put("solenoid", 100);
And not surprisingly: when you modify that in-memory data structure, you modify your data!
In other words: your assumption is simply wrong. Imagine you have some standard Java Tree implementation that has a bunch of nodes. Now you identify a particular Node object within that tree, and change the value of that Node. Of course, that changes the content of the Tree as well, because that Node sits inside that Tree!
Long story short: you read data into memory, you specially target a certain part of that data, you change the data, the data is changed. That is all there is to this!
And just for the record: in the end, we are talking about the semantics of the underlying JSON library. The library you are using here ... simply doesn't copy or clone data when you ask for a sub node. It simply gives you a "pointer" right into the data. Other libraries might do that differently, one could imagine for example that all data is read only, and that modifications are done via returning a completely new Node object, decoupled from the initial data.
In order to not change the initial jsonNode object, the only option seems to be to parse your data twice. So create completely independent JsonNode by processing your input two times. Which of course doubles the amount of work that your code is doing.
Upvotes: 1