Retrieve name of fields of a JSONObject - Java - java

I have to retrieve all name of fields of JSONObjectin Java.
For example, this is a JSON:
{
"name" : {
"first" : "John",
"last" : "McCarthy"
},
"birth" : ISODate("1927-09-04T04:00:00.000Z"),
"death" : ISODate("2011-12-24T05:00:00.000Z"),
"contribs" : [
"Lisp",
"Artificial Intelligence",
"ALGOL"
]
}
This JSON object is just an example, I can't know what a JSONObject contains since I import it. I don't have any information about the name of fields to use Gson/Jackson to deserialization.
Suppose I have a JSONObject myDocJson that contains the previous JSON Object, I use an iterator:
Iterator<?> keys = myDocJson.keySet().iterator();
while(keys.hasNext()) {
System.out.println(keys.next());
}
And as a result I get:
name
birth
death
contribs
But for example I don't have name.first and name.last. So this iterator does not work with innested Object.

You are only printing the keys.
To get the values, try
JSONObject object = null; // your json object
for (Object key : object.keySet()) {
System.out.println(key + "=" + object.get(key)); // to get the value
}
EDIT
And for the objects inside of your JSONObject try
JSONObject object = null; // your json object
for (Object key : object.keySet()) {
System.out.println(key + "=" + object.get(key)); // to get the value
for (Object subKey : ((JSONObject) object.get(key)).keySet()) {
System.out.println(subKey + "=" + object.get(subKey));
}
}

Related

Java json object replace keys names

I have Json like this:
{
"_id" : ObjectId("5e99f6d16cbddf7dad26557f"),
"channel_id" : 49066,
"timestamp" : NumberLong(1580982302003),
"values" : {
"some id" : "81151501",
"some title" : "Some title",
"some address" : "https://www.some-address.com",
"new hash" : {
"some value" : "5",
"other value" : " 54.10 BRL"
},
"wrong values" : "This text have wrong & values & and netx is wrong too & and this &"
},
"null value" : null,
"zero integer" : 0
}
I need to loop through each key and replace spaces with snake_case, for example from other value to other_value
Additionally, I wanted to check every value in the loop by replacing the character & with _, for example:
from This text have wrong & values & and netx is wrong too & and this & to This text have wrong _ values _ and netx is wrong too _ and this _
My json object is made from:
JSONobject jsonObject = new JSONobject(jsonString)
You could iterate over the keys, normalize the key and recursively continue as long as the value is a JSONObject. If it's not, then you could normalize the value as well. So this would look something like this:
static JSONObject normalize(JSONObject object) throws JSONException {
JSONObject result = new JSONObject();
Iterator iterator = object.keys();
while (iterator.hasNext()) {
String key = (String) iterator.next();
String normalizedKey = key.replace(" ", "_");
Object inner = object.get(key);
if (inner instanceof JSONObject) {
result.put(normalizedKey, normalize((JSONObject) inner));
} else if (inner instanceof String) {
result.put(normalizedKey, object.getString(key).replace("&", "_"));
} else {
result.put(normalizedKey, inner);
}
}
return result;
}
Latest version of the library also provides the ability to obtain a keyset, which would allow for a slightly cleaner looping of the keys:
static JSONObject normalized(JSONObject object) {
JSONObject result = new JSONObject();
object.keySet().forEach(key -> {
String normalizedKey = key.replace(" ", "_");
Object value = object.get(key);
if (value instanceof JSONObject) {
result.put(normalizedKey, normalized((JSONObject) value));
} else if (value instanceof String) {
result.put(normalizedKey, ((String) value).replace("&", "_"));
} else {
result.put(normalizedKey, value);
}
});
return result;
}

NullPointer exception while parsing JSON Map in java

I'm trying to parse productId, name, and price from my below JSON in the REST API - but I'm getting null pointer exception when I try to get he name - String name = (String) obj.get("name");, may I know what I'm doing wrong here?
Any help would be really appreciated.
Thanks!
JSON:
{
"id": "af0b86eb-046c-4400-8bc4-0e26042b8f53",
"products": [{
"productId": "1234",
"name": "apple",
"price": "383939"
}
]
}
Controller.java
public ResponseEntity<Object> create(#RequestBody Map<String, Object> obj) {
Product response = myservice.create(obj);
return new ResponseEntity<Object>(response, HttpStatus.CREATED);
}
Service.java
public Product create(Map<String, Object> obj) {
for (Entry<String, Object> entry : obj.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
}
Object [] products = (Object[]) obj.get("products");
HashMap <String, Object> productOne = (HashMap) products[0];
String productId = (String) productOne.get("name");
System.out.println("productId: " +productId);
String name = (String) obj.get("name");
System.out.println("name: " +name);
}
Output:
Key : products Value : [{productId=1234, name=apple, price=383939}]
By obj.get("name"), you try getting value by key name from a top-level of your json request, while it's a property of a second-level object
In pseudo-code (skipping casting and null-checks) it should look like this:
obj.get("products")[0].get("name")
In Service.java you print obj inside for loop. Your print says that key is products and value is an array of objects.
So in following line obj is that top-level object and not contains “name” field.
String name = (String) obj.get("name");
System.out.println("name: " +name);
What if you call obj.get(“products”) and try to cast it into a collection? Then trying to fetch the first index from the collection. It should contain the inner object which contains name key and value.
You should reason exactly as you see the json, by depth(or level).
Initially the whole json is contained in the obj map which contains two key-value pairs:
(key = "id", value = "af0b86eb-046c-4400-8bc4-0e26042b8f53")
(key = "products", value = [{"productId": "1234", "name": "apple", "price": "383939"}])
Since you are interested in product details, the first step is two extract the array products like this:
Object [] products = obj.get("products");
Now product is an array of objects. Since you know that your objects are in turn hash maps you can cast each object to a map and access the key(s) that you want:
HashMap <String, Object> productOne = (HashMap) products[0];
String productId = (String) productOne.get("productId");
String name = (String) productOne.get("name");
..

How do we retrieve all keys along with their prefixes from a JSON document

{
"empId":"1",
"name":"Alex",
"role":"president",
"phone":"123",
"address": {
"street":"xyz",
"city":"hyd",
"pincode":400123
}
}
I want to retrieve keys as following so that I can allow the user to choose such keys in the UI.
keys: ["empId","name","role","phone", "address", "address.street", "address.city",
"address.pincode"]
The same can be used for querying on Mongo directly. I tried using JSONObject and get keys but I am unable to fetch documents along with the path they come from.
Please let me know if there's a direct way I can use in Java or if Mongo has a way to get all keys from where they are coming
You can do that using recursion.
Here is an example:
public static void main(String[] args) throws ParseException {
String str = "{ \"empId\":\"1\", \"name\":\"Alex\", \"role\":\"president\", \"phone\":\"123\", \"address\": { \"street\":\"xyz\", \"city\":\"hyd\", \"pincode\":400123 }}";
JSONObject obj = (JSONObject) new JSONParser().parse(str);
List<String> keysList = new ArrayList<>();
recLevels(keysList, obj, "");
System.out.println(keysList);
}
public static void recLevels(List<String> keysList, JSONObject obj, String prefix) {
Set<String> keys = (Set<String>) obj.keySet();
for (String key : keys) {
keysList.add(prefix + (prefix.isEmpty() ? "" : ".") + key);
if (obj.get(key) instanceof JSONObject) {
recLevels(keysList, (JSONObject) obj.get(key), prefix + (prefix.isEmpty() ? "" : ".") + key);
}
}
}
What the recLevels method does is to go through all the keys of an object and check is any of these keys has an object as its value if (obj.get(key) instanceof JSONObject), if it does recLevels is called again for that object and the process is repeated for that object (one level down).
The important part here is the prefix variable which is used to store the previous keys on the previous levels.
You can create additional array and push all keys in that array.
Use JSON.Stringyfy function to present it as string to end user.
var keys = [],
sourceArray = [{
"empId":"1",
"name":"Alex",
"role":"president",
"phone":"123",
"address": {
"street":"xyz",
"city":"hyd",
"pincode":400123
}
}]; //Test data
$.each(sourceArray, function(k, v) {
//k is the key and v is the value (key-value pair)
keys.push(k);
});
//You have all the keys - use at your disposal
Note: I've not tested this code in absence of source-code, please validate and modify as per your actual code.

Trying to read data from external JSON file but the order in which data is read is not correct i.e random

I have a JSON file in which the number of objects may vary, I want to read those objects using loop. But the order in which the data is read from JSON is different. I need data to read in same order as specified in JSON file.
Object obj = parser.parse(new FileReader("D:\\demo.json"));
JSONObject jsonObject = (JSONObject) obj;
for (Object key : jsonObject.keySet()) {
//based on you key types
String keyStr = (String)key;
Object keyvalue = jsonObject.get(keyStr);
//Print key and value
System.out.println("key: "+ keyStr + " value: " + keyvalue);
if(Driver.driver.findElement(By.name(keyStr)).isDisplayed() && Driver.driver.findElement(By.name(keyStr)).isEnabled())
Driver.driver.findElement(By.name(keyStr)).sendKeys((keyvalue.toString()));

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());
}

Categories

Resources