decoding Jackson Tree Model - java

DATA1 = {"metrics": {"code1": 0, "code2" : 100} }
DATA2 = {"metrics": {"code1": [10,20,30]}}
CODE
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(m);
JsonNode metric_node = rootNode.path("metrics");
Iterator iterator = metric_node.getFields();
while (iterator.hasNext()) {
logger.info("class_name=> {}", iterator.next().getClass().getName());
logger.info("content=> {}", iterator.next());
}
OUTPUT (for DATA1)
class_name=> java.util.LinkedHashMap$Entry
content=> code1=0
class_name=> java.util.LinkedHashMap$Entry
content=> code2=100
Don't know about DATA2
I am not able to iterate through the hashmap.I tried iterator.next().getKey() etc. but not working. How do I

You are only iterating over the outer keys of the JsonNode you are visiting. And since you are printing out the name of the actual class, that is why you are getting the logged output about the LinkedHashMap$Entry. Take a look at the return type of the metric_node.getFields();
Iterator<Map.Entry<String, JsonNode>> iterator = metric_node.fields();
You are essentially iterating over each node at that level. But since you call iterator.next() twice, you are hitting both keys and the loop is terminating. If you tried to run this code on DATA2, you would get a NoSuchElementException because you are iterating over more items than your iterator actually knows about.
So, you are not actually looking at any of the values associated with those keys. If you change how your loop processes the JsonNodes you will see what keys/values are at each field. If you have nested objects that you wanted to go through, you would need to traverse through each JsonNode
JsonNode rootNode = mapper.readTree(DATA1);
JsonNode metric_node = rootNode.path("metrics");
Iterator<Map.Entry<String, JsonNode>> iterator = metric_node.fields();
while (iterator.hasNext()) {
Map.Entry<String, JsonNode> next = iterator.next();
System.out.println("class_name=> = " + next.getKey());
System.out.println("content=> = " + next.getValue());
System.out.println();
}
Output:
class_name=> = code1
content=> = 0
class_name=> = code2
content=> = 100

Related

Remove whitespace from json using jackson

I have a simple JSON like this:
{
"enums" : [{"someName" : " someValue ", etc.. }]
}
Sometimes, someValue has whitespace in it. (ie. " someValue ")
I can't seem to get how to SET each value back to the node. I have this:
JsonNode values = root.get("enumValues");
Iterator<Entry<String, JsonNode>> nodes = values.getFields();
while (nodes.hasNext()) {
Map.Entry<String, JsonNode> entry = (Map.Entry<String, JsonNode>) nodes.next();
// what do I do here?
}
I know that JsonNodes are imutable, but how do I get the JsonObjects? <String, JsonObject> wont work.
I want to be able to parse this as an object (I eventually want to make in recursive for more complex JSON, but one thing at a time) so that when I
print the JSON out it would look like this:
{
"enums" : [{"someName" : "someValue", etc.. }]
}
Given a JSON example
{
"enums" : [{"someName" : " someValue ", "a": " b "}]
}
you can do it like this:
(I also added some code to read the JSON input and to print the JSON output,
and fixed some flaws in your code to make it compilable)
ObjectMapper objectMapper = new ObjectMapper();
File file = new File("example.json");
JsonNode root = objectMapper.readValue(file, JsonNode.class);
ArrayNode arrayNode = (ArrayNode) root.get("enums");
ObjectNode objectNode = (ObjectNode) arrayNode.get(0);
Iterator<Map.Entry<String, JsonNode>> nodes = objectNode.fields();
while (nodes.hasNext()) {
Map.Entry<String, JsonNode> entry = nodes.next();
if (entry.getValue().isTextual()) {
String s = entry.getValue().asText(); // get string from JSON node
s = s.trim(); // remove leading/trailing space
objectNode.put(entry.getKey(), s); // put the string back into JSON node
}
}
objectMapper.writeValue(System.out, root);
Then you get the JSON output
{"enums":[{"someName":"someValue","a":"b"}]}

How to convert a nested jsonObject to a hashMap with updated field names in java with Jackson?

UPDATE: updated the codebase and now I am getting the key values pairs but there is some issue with the recursion logic while adding key|value pair. Need help with fixing this code.
OLD ISSUE:I have been trying to convert a JSON into a HashMap but as the JSON is a nested object I am unable to save the key name for the nested fields during recursion calls. Below is the updated sample code:
private HashMap<String,Object> addToMap(JsonNode jsonNode, HashMap<String, Object> map) {
// TODO Auto-generated method stub
if (jsonNode.isObject()) {
ObjectNode objectNode = (ObjectNode) jsonNode;
Iterator<Map.Entry<String, JsonNode>> iter = objectNode.fields();
while (iter.hasNext()) {
Map.Entry<String, JsonNode> entry = iter.next();
parentKey=entry.getKey();
//set key from the mapperLookup.
map.put(parentKey, addToMap(entry.getValue(),new HashMap<String,Object>()));
}
} else if (jsonNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) jsonNode;
for (int i = 0; i < arrayNode.size(); i++) {
//set key from the mapperLookup.
map.put(parentKey, addToMap(arrayNode.get(i),new HashMap<String,Object>()));
}
} else if (jsonNode.isValueNode()) {
ValueNode valueNode = (ValueNode) jsonNode;
//set key from the mapperLookup.
map.put(parentKey, valueNode.asText());
}
return map;
}
Sample input:
{
"S_name":"xyz",
"K_id":"12233",
"N_dum":[{"K_id":"dfff"},{"S_nam":"dfgg"}]
}
expected output:
{S_name=xyz,
K_id=12233,
N_dum={K_id=dfff,S_nam=dfgg}
}
Current output:
{S_name={S_name=xyz}, K_id={K_id=12233}, N_dum={N_dum={K_id={K_id=dfff}}, K_id={S_nam={S_nam=dfgg}}}}
Improvements would be helpful.
As I need to do some transformation with the key names that's why I am following this approach.
You can try using ObjectMapper like following:
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> dataRaw = null;
dataRaw = mapper.readValue(rawValues, new TypeReference<Map<String, Object>>() {});
which rawValues is a json string.

Is there any simple way to extract the key-value pairs from a JSON string for a given key using jackson libraries? (Java)

I have this json response:
{
"Name": "tardis",
"Driver": "custom",
"Mountpoint": "/var/lib/docker/volumes/tardis/_data",
"Status": {
"hello": "world"
},
"Labels": {
"com.example.some-label": "some-value",
"com.example.some-other-label": "some-other-value"
},
"Scope": "local"
}
From this response, I want to parse the key-value pairs inside "Labels" key. Currently my method to extract those looks like this:
//"json" is the JSON response as a string
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
Iterator<Entry<String, JsonNode>> it = root.fields();
while (it.hasNext())
{
Map.Entry<String, JsonNode> entry = it.next();
JsonNode n = entry.getValue();
String nlabel = entry.getKey();
if (nlabel != null && nlabel.equals(key))
{
Iterator<Entry<String, JsonNode>> itr = n.fields();
while (itr.hasNext())
{
Map.Entry<String, JsonNode> it2 = itr.next();
String labelKey = it2.getKey();
String labelValue = it2.getValue().toString();
System.out.println();
}
}
}
I am able to retrieve those key value pairs using this logic, but I want to make it simpler because I want to make it work when there is a deeper nesting involved.
Is there a simpler, better way to do it using jackson libs?

print values from json file

I'm using the following code to get JSON data from file, currently I was able to achieve the JSON but in one string. I want to parse it to array. The json file is like this:
{
"employee": [
{
"name": "joan",
"lastname": "test",
"age": 23
},
I'm using the following code to get the data but I get it in one string and I want to print some of the data
JSONObject jsonObject = (JSONObject) parser
.parse(new FileReader("C:\\MockData\\Json\\js.txt"));
JSONParser parser1 = new JSONParser();
ContainerFactory containerFactory = new ContainerFactory() {
public List<?> creatArrayContainer() {
return new LinkedList<Object>();
}
public Map<?, ?> createObjectContainer() {
return new LinkedHashMap<Object, Object>();
}
};
Map<?, ?> json = (Map<?, ?>) parser1.parse(jsonObject.toJSONString(), containerFactory);
Iterator<?> iter = json.entrySet().iterator();
System.out.println("==iterate result==");
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
System.out.println(entry.getKey() + "=>" + entry.getValue());
}
this is the output
employee=[{age=23, name=joan, lastname=test}, {age=22, name=Alex, lastname=avz}, {age=65, name=Dan, lastname=severn}]
Here the entry.getValue() is retuen one concatenated string of the array,
the while is running just one time...
but I want to loop on it to take the key value. How should I do that?
for example if I want to print name alex witn age 22 how should I do that?
Note: The file can be changed so I don't know the keys (now its name but in can be firstName and any other field for that i need generic solution).
if there is a way to use different parser that can do that Im open.
The following is the full solution to your question.
With this code you can break down the data to each employee and also separate the employee attributes.
Set<String> keySet = jsonObject.keySet();
Iterator keySetIterator = keySet.iterator();
while(keySetIterator.hasNext()){
JSONArray array = (JSONArray)jsonObject.get(keySetIterator.next());
while(employeeKeySetIterator.hasNext()){
String employeeKey = employeeKeySetIterator.next().toString();
System.out.println(employeeKey + " : "+ employee.get(employeeKey));
}
}
}
You need to cast the inner json string to a JSONArray
JSONArray array = (JSONArray)jsonObject.get("employee");
Iterator<JSONObject> iterator = array.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toString());
}

Jackson JSON: get node name from json-tree

How can I receive the node names from a JSON tree using Jackson?
The JSON-File looks something like this:
{
node1:"value1",
node2:"value2",
node3:{
node3.1:"value3.1",
node3.2:"value3.2"
}
}
I have
JsonNode rootNode = mapper.readTree(fileReader);
and need something like
for (JsonNode node : rootNode){
if (node.getName().equals("foo"){
//bar
}
}
thanks.
For Jackson 2+ (com.fasterxml.jackson), the methods are little bit different:
Iterator<Entry<String, JsonNode>> nodes = rootNode.get("foo").fields();
while (nodes.hasNext()) {
Map.Entry<String, JsonNode> entry = (Map.Entry<String, JsonNode>) nodes.next();
logger.info("key --> " + entry.getKey() + " value-->" + entry.getValue());
}
This answer applies to Jackson versions prior to 2+ (originally written for 1.8). See #SupunSameera's answer for a version that works with newer versions of Jackson.
The JSON terms for "node name" is "key." Since JsonNode#iterator()
does not include keys, you need to iterate differently:
for (Map.Entry<String, JsonNode> elt : rootNode.fields())
{
if ("foo".equals(elt.getKey()))
{
// bar
}
}
If you only need to see the keys, you can simplify things a bit with JsonNode#fieldNames():
for (String key : rootNode.fieldNames())
{
if ("foo".equals(key))
{
// bar
}
}
And if you just want to find the node with key "foo", you can access it directly. This will yield better performance (constant-time lookup) and cleaner/clearer code than using a loop:
JsonNode foo = rootNode.get("foo");
if (foo != null)
{
// frob that widget
}
fields() and fieldNames() both were not working for me. And I had to spend quite sometime to find a way to iterate over the keys. There are two ways by which it can be done.
One is by converting it into a map (takes up more space):
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> result = mapper.convertValue(jsonNode, Map.class);
for (String key : result.keySet())
{
if(key.equals(foo))
{
//code here
}
}
Another, by using a String iterator:
Iterator<String> it = jsonNode.getFieldNames();
while (it.hasNext())
{
String key = it.next();
if (key.equals(foo))
{
//code here
}
}
Clarification Here:
While this will work:
JsonNode rootNode = objectMapper.readTree(file);
Iterator<Map.Entry<String, JsonNode>> fields = rootNode.fields();
while (fields.hasNext()) {
Map.Entry<String, JsonNode> entry = fields.next();
log.info(entry.getKey() + ":" + entry.getValue())
}
This will not:
JsonNode rootNode = objectMapper.readTree(file);
while (rootNode.fields().hasNext()) {
Map.Entry<String, JsonNode> entry = rootNode.fields().next();
log.info(entry.getKey() + ":" + entry.getValue())
}
So be careful to declare the Iterator as a variable and use that.
Be sure to use the fasterxml library rather than codehaus.
JsonNode root = mapper.readTree(json);
root.at("/some-node").fields().forEachRemaining(e -> {
System.out.println(e.getKey()+"---"+ e.getValue());
});
In one line Jackson 2+

Categories

Resources