I want to extract a key and its value from json object. I am having a 3 objects in a json with parent child relation, named as
1. Parent,
2. childOne_OfParent and
3. child_OF_childOne.
I want to extract all the value of "userQueryId" from child_OF_childOne and store into a string type variable.
How do I perform this. Thanks in advance.
My Json object is:
{
"createdBy": "****",
"dashboardId": 1,
"childOne_OfParent": [
{
"createdBy": null,
"dashboardSectionId": 1,
"child_OF_childOne": [
{
"createdBy": "XYZ",
"userQueryId": "283"
},
{
"createdBy": "ABC",
"userQueryId": "284"
},
{
"createdBy": "AWS",
"userQueryId": "285"
}
]
}
]
}
You can use the json to create a model java class like this. I used your json to create the class using the site https://codebeautify.org/json-to-java-converter. You can give a classname of your choice in the Class_Name.
public class Class_Name {
private String createdBy;
private float dashboardId;
ArrayList < Object > childOne_OfParent = new ArrayList < Object > ();
// Getter Methods
public String getCreatedBy() {
return createdBy;
}
public float getDashboardId() {
return dashboardId;
}
// Setter Methods
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public void setDashboardId(float dashboardId) {
this.dashboardId = dashboardId;
}
}
Then you can use the Jackson to convert your json into a java object and access the data you want. Here jsonString is your json and the objResp is your object.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Class_Name objResp = mapper.readerFor(Class_Name.class).readValue(jsonString);
Here is a useful guide for that. https://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
The tool for these kind of tasks is JsonPath. It has xpath-like search capabilities.
Here is a working example of the given question
public static void main(String[] args) {
String searchQueryIds = "$.childOne_OfParent[*].child_OF_childOne[*].userQueryId";
try (InputStream is = Files.newInputStream(Paths.get("c:/temp/test.json"))) {
List<String> ids = JsonPath.parse(is).read(searchQueryIds);
System.out.println(ids);
} catch (Exception e) {
e.printStackTrace();
}
}
Assuming there is pojo for json and jackson library available. It will return comma separated queryUserIds.
Parent parent = new ObjectMapper().reader(Parent.class).readValue(inputJson);
String userIds = parent.getChildOne_OfParent().get(0).getChild_OF_childOne().stream()
.map(c -> c.getuserQueryId())
.collect(Collectors.joining(","));
Related
I want to read a JSON file received.
That's the form of the JSON file:
{
"name": "list_name"
"items": [
{
"id": 4
},
{
"id": 3
},
{
"id": 2
},
]
}
I want to parse that JSON that represents a movie list, and the id's of the movies. I want to extract the ids and the name.
#PUT
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
public Response deleteMoviesFromList2(#Context HttpServletRequest req) Long movieListId) {
Long userId = getLoggedUser(req);
getLoggedUser(req);
final String json = "some JSON string";
final ObjectMapper mapper = new ObjectMapper();
return buildResponse(listMovieService.remove(¿?));
}
I want to extract the ids but I have no clue how to do it.
You can convert json string using ObjectMapper class like this.
ObjectMapper objectMapper = new ObjectMapper();
String carJson =
"{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
try {
Car car = objectMapper.readValue(carJson, Car.class);
System.out.println("car brand = " + car.getBrand());
System.out.println("car doors = " + car.getDoors());
} catch (IOException e) {
e.printStackTrace();
}
Here you can replace Car class with your custom Movie class and you are done.
If you have a movie class defined, such as:
class Movie {
String id;
//getters
//setters
}
and a Movie list class:
class MovieList {
String name;
List<Movie> items;
//getters
//setters
}
Then you can use an object mapper with an inputStream:
try(InputStream fileStream = new FileInputStream("movielist.json")) {
MovieList list = mapper.readValue(fileStream, MovieList.class);
}
ObjectMapper's readValue has an overloaded version that takes an input stream, and that's the one used above.
I want to get a part of list json from a whole nested one. I have a json that looks like following:
{
"response": 200,
"responseMsg": "Allright",
"location": [
{
"stateId": 1,
"stateName": "West Bengal",
"district": [
{
"districtId": 15,
"districtName": "abc",
"village": [
{
"villageId": 121,
"villageName": "ABC"
},
{
"villageId": 90,
"villageName": "XYZ"
}
]
},
{
"districtId": 11,
"districtName": "xyz",
"village": [
{
"villageId": 58,
"villageName": "PQR"
}
]
}
]
}
]
}
I have written the bean files as following :
Details.java:
public class Details {
private int response = 0;
private String responseMsg = null;
private List<State> states = null;
public List<State> getLocation() {
return location;
}
State.java:
public class State {
private int stateId = 0;
private String stateName=null;
private List<District> district;
public List<District> getDistrict() {
return district;
}
Now, I want only the State json differently so that I can then use use it as List to populate the spinner in android.
For parsing the json, I am using
Gson googleJson = builder.create();Details details = googleJson.fromJson(result, Details.class);
List<State> stateList = details.getLocation();
But when i again convert this to json using gson.toJson(stateList) this gives:
[
{
"district": [
{
"village": [
{
"villageName": "Mekhliganj",
"villageId": 57
}
],
"districtName": "Cooch Bihar",
"districtId": 10
}
],"stateName=West Bengal","stateId":1
}
}
But this is other way round as state name goes in end when i again convert it to json.
Also , this same json (stateList) gives null pointer exception when I again try to parse it as:
State stateObj = gson.fromJson(stateList,State.class);
What should be the correct way to do this ? i.e. get a part of json (list) from a whole using gson and parse that part ?
Got the solution for you...
You are not passing the whole response in below function
try this steps to get whole response :
1) Store the data in String or any object class you are storing.
2)
Gson gson = new Gson();
String string = gson.toJson(response);
Note : You are just parsing remaining response. You are not parsing the original response. Just recheck the response when you parse in above function by putting break point on it.
public class Details {
private int response = 0;
private String responseMsg = null;
private Location location = null;
//add getter and setter
}
public class Location{
private List<State>stateList;
//add getter and setter
}
Finally
public class State {
private int stateId = 0;
private String stateName=null;
private List<District> district;
//add getter and setter
}
I have a json format which I am converting into Java Object Model using Jackson API. I am using Jaxsonxml 2.1.5 parser. The json response is as shown below.
{
"response": {
"name": "states",
"total-records": "1",
"content": {
"data": {
"name": "OK",
"details": {
"id": "1234",
"name": "Oklahoma"
}
}
}
}
}
Now json response format has changed. If the total-records is 1 the details will be an object with id and name attributes. But if the total-records is more than 1 then the details will be an array of object like below:
{
"response": {
"name": "states",
"total-records": "4",
"content": {
"data": {
"name": "OK",
"details": [
{
"id": "1234",
"name": "Oklahoma"
},
{
"id": "1235",
"name": "Utah"
},
{
"id": "1236",
"name": "Texas"
},
{
"id": "1237",
"name": "Arizona"
}
]
}
}
}
}
My Java Mapper class looks like below with earlier json response.
#JsonIgnoreProperties(ignoreUnknown = true)
public class MapModelResponseList {
#JsonProperty("name")
private String name;
#JsonProperty("total-records")
private String records;
#JsonProperty(content")
private Model model;
public Model getModelResponse() {
return model;
}
public void setModel(Model model) {
this.model = model;
}
}
Client Code
package com.test.deserializer;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com..schema.model.Person;
public class TestClient {
public static void main(String[] args) {
String response1="{\"id\":1234,\"name\":\"Pradeep\"}";
TestClient client = new TestClient();
try {
Person response = client.readJSONResponse(response1, Person.class);
} catch (Exception e) {
e.printStackTrace();
}
}
public <T extends Object> T readJSONResponse(String response, Class<T> type) {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
T result = null;
try {
result = mapper.readValue(response, type);
} catch (Exception e) {
e.printStackTrace();
}
return (T) result;
}
}
Now based on the total-records how to handle to mapping to either a Model or list of Model Object. Please let me know.
You need a custom deserializer. The idea is to mix and match object processing with tree processing. Parse objects where possible but use the tree (JSONNode) for custom handling.
On the MapModelResponseList, remove the records property and add a List<Data> array where Data is just a holder class for the id/name pairs. You can get the total records by returning the size of this list.
In the deserializer, do the following:
public final class MapModelDeserializer extends BeanDeserializer {
public MapModelDeserializer(BeanDeserializerBase src) {
super(src);
}
protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, Object beanOrClass, String propName) throws IOException, JsonProcessingException {
if ("content".equals(propName)) {
MapModelResponseList response = (MapModelResponseList) beanOrClass;
// this probably needs null checks!
JsonNode details = (JsonNode) jp.getCodec().readTree(jp).get("data").get("details");
// read as array and create a Data object for each element
if (details.isArray()) {
List<Data> data = new java.util.ArrayList<Data>(details.size());
for (int i = 0; i < details.size(); i++) {
Data d = jp.getCodec().treeToValue(details.get(i), Data.class);
data.add(d);
}
response.setData(data);
}
// read a single object
else {
Data d = jp.getCodec().treeToValue(details, Data.class);
response.setData(java.util.Collections.singletonList(d));
}
super.handleUnknownProperty(jp, ctxt, beanOrClass, propName);
}
Note that you do not implement deserialize() - the default implementation is used to create the MapModelResponseList as normal. handleUknownProperty() is used to deal with the content element. Other data you don't care about is ignored due to #JsonIgnoreProperties(ignoreUnknown = true) in the super call.
This is a late answer, but I solve it in a different way. It can work by catching it in Object like this:
#JsonProperty("details")
public void setDetails(Object details) {
if (details instanceof List) {
setDetails((List) details);
} else if (details instanceof Map) {
setDetails((Map) details);
}
}
public void setDetails(List details) {
// your list handler here
}
public void setDetails(Map details) {
// your map handler here
}
I have a server that produces the following JSON with Jackson.
{
"$id" : 1,
"employees" : [
{
"$id" : 2,
"name" : "John Rambo",
},
2 // Jackson: reference by ID only
]
}
The list of employees contains the same employee twice. Jackson correctly references the object by it's ID the second time.
I want to deserialize this in a client that uses JSON.net, but this won't work because JSON.net expects me to have the reference wrapped in a json object with a $ref property like this:
{
"$id": "1",
"employees" : [
{
"$id": "2",
"name": "John Rambo"
},
{
"$ref": "2" // JSON.net: reference wrapped in JSON object
}
]
}
Is there a way to make JSON.net correctly consume the Jackson syntax either by configuration or by implementing a custom deserializer?
Here's a custom converter that should work:
public class EmployeeConverter : JsonConverter
{
public override void WriteJson(
JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
List<Employee> employees = null;
if (reader.TokenType == JsonToken.StartArray)
{
JArray arr = serializer.Deserialize<JArray>(reader);
employees = new List<Employee>(arr.Count);
var employeeMap = new Dictionary<int, Employee>();
foreach (var item in arr)
{
if (item.Type == JTokenType.Object)
{
var employee = item.ToObject<Employee>();
employees.Add(employee);
int id = item["$id"].ToObject<int>();
employeeMap.Add(id, employee);
}
else if (item.Type == JTokenType.Integer)
{
Employee employee = null;
int id = item.ToObject<int>();
if (employeeMap.TryGetValue(id, out employee))
{
employees.Add(employee);
}
}
}
}
return employees;
}
public override bool CanRead
{
get { return true; }
}
public override bool CanConvert(Type objectType)
{
return false;
}
}
... and here's how you'd use it:
public class Company
{
public Company()
{
this.Employees = new List<Employee>();
}
[JsonConverter(typeof(EmployeeConverter))]
public List<Employee> Employees { get; set; }
}
Example: https://dotnetfiddle.net/XooyQC
Basically use a custom converter to deserialize the entire array. First, deserialize the array to a JArray, then inspect each element of the JArray to see if it's a reference or a new object.
I have the followed snipets of Json String:
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
}
}
}
I use some methods to convert this String to Object:
private static Gson mGson = new Gson();
...
public static WebObjectResponse convertJsonToObject(String jsonString) {
WebObjectResponse webObjectResponse = null;
if(jsonString != null && jsonString.length() > 1){
webObjectResponse = mGson.fromJson(jsonString, WebObjectResponse.class);
}
return webObjectResponse;
}
Where WebObjectResponse is class that should represent above mentioned String.
Its not complicated if I get static fields.
But in my case the values have different names: tech11, tech12 ....
I can use #SerializedName but its works in specific cases like convert "class" to "class_".
As you see networks Object defined as list of tech Objects but with different post-fix.
public class WebObjectResponse{
private DataInfoList networks = null;
}
This is static implementation, i defined 2 values tech11 and tech12 but next response might be techXX
public class DataInfoList {
private DataInfo tech11 = null;
private DataInfo tech12 = null;
}
public class DataInfo {
private String id = null;
private String name = null;
}
What is the good way to convert current Json String to Object where list of elements are Objects too and have different names?
Thank you.
Use a Map!
I would do the following
public class WebObjectResponse {
private Map<String, DataInfo> networks;
}
public class DataInfo {
private String id = null;
private String name = null;
}
// later
Gson gson = new Gson();
String json = "{\"networks\": {\"tech11\": { \"id\": \"1\",\"name\": \"IDEN\" }, \"tech12\": { \"id\": \"2\", \"name\": \"EVDO_B\" } }}";
WebObjectResponse response = gson.fromJson(json, WebObjectResponse .class);
For each object in json networks, a new entry will be added to the Map field of your class WebObjectResponse. You then reference them by techXX or iterate through the keyset.
Assuming a structure like this
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
},
"tech13": {
"id": "3",
"name": "WOHOO"
}, ...
}
}
We would need your class structure for more details.
As far as I am aware, I think you will need to have some mappings defined somewhere (I used xml's) and then try to match json with one of the mappings to create objects.
Google gson is good. I did it in Jackson
Also, converting objects should be trivial. But since you might have variable fields like tech11 and tech12 , you might want to store the "network" value as a string and then extract fields out of it when required.
Hope I could help.
Edit : Sotirious nails it.
Please use this link for converting SON Response to Java POJO class
http://www.jsonschema2pojo.org/