So what you have is a JSON object, so JsonNode.Parse will really return a JsonObject, so first we need to cast it:
var jsonObject = JsonNode.Parse(input)!.AsObject(); // null check omitted for brevity
Now let's do the rename. A rename is really a removal of the object with the old property followed by readding it with the new name. So:
var node = jsonObject["foo"]; // take a reference to foo so we don't lose it
jsonObject.Remove("foo"); // detach from parent
jsonObject.Add("bar", node); // attach with new name
The reason why you need to first remove it and then add it back, is that JsonNode objects have parents, and you're not allowed to add a node to an object or array if it already has a parent. So you first need to detach it from its parent with Remove, and then you can add it back under the new name with Add.
Now, this modifies the original JSON object. If you want to instead keep the original intact you'll have to clone it first. This is a problem, because there is no way to clone a JsonNode. You could do this:
var clone = new JsonObject(jsonObject);
And it will compile, but then at runtime you'll hit an exception because this just adds the nodes from one object to the next and as we've already established you can't add an object that already has a parent to another one. You would have to first clone each child node and add those instead.
As far as I'm aware, the JsonNodes namespace has no way to do a deep clone of JSON nodes. It seems like an oversight. You could either do it by hand by recursively enumerating the nodes in the document and creating them, or just parse the document twice.
Working with jsonnode class
Does it consider a bad practice to use jsonNode as the return type
Conversion between JsonElement and JsonNode
jackson - How to get JSON Object from JSONNode Array? - Stack Overflow
Videos
So what you have is a JSON object, so JsonNode.Parse will really return a JsonObject, so first we need to cast it:
var jsonObject = JsonNode.Parse(input)!.AsObject(); // null check omitted for brevity
Now let's do the rename. A rename is really a removal of the object with the old property followed by readding it with the new name. So:
var node = jsonObject["foo"]; // take a reference to foo so we don't lose it
jsonObject.Remove("foo"); // detach from parent
jsonObject.Add("bar", node); // attach with new name
The reason why you need to first remove it and then add it back, is that JsonNode objects have parents, and you're not allowed to add a node to an object or array if it already has a parent. So you first need to detach it from its parent with Remove, and then you can add it back under the new name with Add.
Now, this modifies the original JSON object. If you want to instead keep the original intact you'll have to clone it first. This is a problem, because there is no way to clone a JsonNode. You could do this:
var clone = new JsonObject(jsonObject);
And it will compile, but then at runtime you'll hit an exception because this just adds the nodes from one object to the next and as we've already established you can't add an object that already has a parent to another one. You would have to first clone each child node and add those instead.
As far as I'm aware, the JsonNodes namespace has no way to do a deep clone of JSON nodes. It seems like an oversight. You could either do it by hand by recursively enumerating the nodes in the document and creating them, or just parse the document twice.
Your question update adds "bar" to an existing node object. if you want to create a new object that is a copy of an existing node object, you can make it 2 main ways
- The simpliest and most efficient way is to change json string
string newInput = input.Replace("\"foo\":","\"bar\":");
var newNode=JsonNode.Parse(newInput);
- Or create new json object
var newNode = new JsonObject( new[] { KeyValuePair.Create<string,JsonNode>("bar",
JsonNode.Parse(node["foo"].ToJsonString()) )});
result
{
"bar": [
{
"a": 1
},
{
"b": null
}
]
}
I am a beginner of Java & Springboot. I feel like I am doing something that does not use the full strength of spring boot, e.g. using JsonNode & return untyped Response Entity etc.
Just wonder if there is any best practice when dealing with this kind of situation, when I want to return an object as part of result.
In Typescript I can create an interface for the object, how about in java / Springboot?
TestService.java
...
@Service
@Slf4j
public class TestService {
private final TsKvRepository tsKvRepository;
private final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
public TestService(TsKvRepository tsKvRepository) {
this.tsKvRepository = tsKvRepository;
}
public DeferredResult<ResponseEntity> getLatestTimeseries(String entityIdStr, String eui64) {
DeferredResult<ResponseEntity> result = new DeferredResult<>();
try {
UUID entityId = UUID.fromString(entityIdStr);
List<TsKvEntity> tsList = this.tsKvRepository.findLatestByEui64(entityId, eui64);
if (!tsList.isEmpty()) {
TsKvEntity tsKvEntity = tsList.get(0);
JsonNode jsonNode = objectMapper.readTree(tsKvEntity.getJsonValue());
ResponseEntity<?> responseEntity = new ResponseEntity<>(jsonNode.get(0), HttpStatus.OK);
result.setResult(responseEntity);
} else {
ResponseEntity<?> responseEntity = new ResponseEntity<>("No data found", HttpStatus.NOT_FOUND);
result.setResult(responseEntity);
}
}catch(IllegalArgumentException | NullPointerException e) {
ResponseEntity<?> responseEntity = new ResponseEntity<>("Invalid UUID format or null keysStr: " + e.getMessage(), HttpStatus.BAD_REQUEST);
result.setResult(responseEntity);
} catch (JsonMappingException e) {
throw new RuntimeException(e);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
return result;
}
}