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");
..
Related
I have the following JSON file:
{
"meta" : {
"stock" : "AWS",
"date modified" : 90
},
"roles" : [ "Member", "Admin" ],
"name" : "John Doe",
"admin" : true,
"email" : "john.doe#example.com"
}
I wanted to both read the values of the keys and add them to an Array List.
try {
// create object mapper instance
ObjectMapper mapper = new ObjectMapper();
// convert JSON file to map
Map<?, ?> map = mapper.readValue(Paths.get("user.json").toFile(), Map.class);
ArrayList<String> data = new ArrayList<String>();
// print map entries
for (Map.Entry<?, ?> entry : map.entrySet()) {
System.out.println((entry.getClass()) + " " + entry.getValue());
data.add((String)entry.getValue()); // trying to add entry values to arraylist
}
} catch (Exception ex) {
ex.printStackTrace();
}
I'm able to print out the data type of the value along with the value itself. All the values are part of class java.util.LinkedHashMap$Entry. I'm not able to cast the values to a String to add them to an ArrayList. How should I go about doing this? Thanks
From the jackson-databind documentation you can convert your json to a Map<String, Object> map with the following line (you have boolean, list, number and string values in your json) :
Map<String, Object> map = mapper.readValue(json, Map.class);
// it prints {meta={stock=AWS, date modified=90}, roles=[Member, Admin], name=John Doe, admin=true, email=john.doe#example.com}
System.out.println(map);
If you want to save your map values string representation into an ArrayList data you can iterate over them with a loop :
List<String> data = new ArrayList<>();
for (Object value : map.values()) {
data.add(value.toString());
}
//it will print [{stock=AWS, date modified=90}, [Member, Admin], John Doe, true, john.doe#example.com]
System.out.println(data);
Your data type of entries will be like:
meta: Map<String:Object>
roles: List<String>
admin: Boolean
So you will get an exception when casting to string for each entry value.
You should handle different data type and convert it according to your request:
Object value = entry.getValue();
I highly recommend you write more few functions to check and convert map/list/primitive variables to expected data (String):
boolean isList(Object obj);
boolean isMap(Object obj);
...
public List<String> convertMap(Map<String,Object> map);
...
{
"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.
I've got my php code:
<?php
require('conn.php');
$json = array();
$newquery = "SELECT * FROM absent";
$newresult = mysqli_query($conn, $newquery);
$jsonData = array();
while ($array = mysqli_fetch_array($newresult)) {
array_push($jsonData,array(
"username"=>$array['username'],
"date"=>$array['date']
));
}
echo json_encode(array("result"=>$jsonData), true);
mysqli_close($conn);
?>
and it returned :
{"result":[{"username":"verarmond","date":"2016-11-17"},{"username":"henk","date":"2016-11-15"}]}
How can i get only usernames and only dates in android ??
Thanks and regard.
HashMap is a data structure based on (key, value) pairs.
So, when you do this:
map.put("iOS", "100");
map.put("Android", "101");
You put the value "100" at "iOS" key, and value "101" at "Android" key.
If you want to access this values, you simply use the "map" object and get the value by the key, like this:
String val1 = map.get("iOS"); //this returns "100"
String val2 = map.get("Android"); // this returns "101"
To get all the entries from a map:
ArrayList<String> values = new ArrayList<>();
for (
Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String Value = entry.getValue();
values.add(Value); //this will add all the values in the hashmap into `values` arraylist
}
It is very easy, you can do it by translating your JSON result to a JSON object with:
JSONObject jsonResult = new JSONObject(jsonString);
Then take your JSON array named result:
JSONArray jsonResultArray = new JSONArray(jsonResult.getJSONArray("result"));
Now you can iterate through your JSON Array to get the required elements:
for(JSONObject jsonObject:jsonResultArray) {
Log.d("TAG", "User: " + jsonObject.getString("username"));
Log.d("TAG", "Date: " + jsonObject.getString("date"));
}
You should know that every { means a JSONObject and the [ means a JSONArray, wit that you should have enough to go.
I wrote the code on the fly and can't check it now, maybe there are some typo or error.
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));
}
}
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());
}