Java Spring custom JSON response - java

I have a data that looks like so:
{
"name":{
"first": "<firstName>",
"last": "<lastName>"
},
"info": "<info>",
"place":{
"location": "<location>",
},
"test": "<test>"
}
However, I want to customize the Response json and group the data by the location.
In other words I would like to have a response like this:
"location":[{
"name": <location>,
user: [{
"name": <firstName> + <lastName>,
"info": <info>,
"test": <test>
}]
}]
I have tried to the it into a map like so:
List<Data> data= newArrayList(repository.findAll(Sort.by(Sort.Direction.ASC, "location")));
Map<String, Object> result= new HashMap<>();
for (Data d : data) {
result.put("name", d.getLocation());
result.put("user", d.getFirstName());
...
and so on, but this does not work. What is the best approach to achieve my desired result?

As of now you have a single result map, which you are then overwriting in the loop, so it will contain data for a location only, the last one. What you probably wanted to do is creating a list of those maps, which requires creating a new map inside the loop, and collecting them in a list:
List<Map<String, Object>> result=new ArrayList<>();
for(Data d : data) {
Map<String, Object> item = new HashMap<>();
item.put("name", d.getLocation());
item.put("user", d.getFirstName());
...
result.add(item);
}

Related

How can I get data from the api graphQL?

I make a request on api graphQL and have the responce of body:
{
"dataRequests": [
{
"status": "success",
"title": "token",
"values": {
"limit": 1,
"offset": 0,
"count": 1,
"total": 1,
"elements": [
{
"type": "DOMAIN",
"permission": "default",
"properties": [
{
"name": "property:id",
"value": 390
},
{
"name": "setting:crawler:token",
"value": "token(here's real token)"
}
],
"filters": []
}
]
}
}
]
}
I want to get value of the field "value" with token. But i have a problem to desirialize it.
My code can get the list of maps of 'dataRequests' field(using RestAssured):
GraphQLSteps graphQLSteps = new GraphQLSteps();
Response response = graphQLSteps.postProjectToken(id);
List<Map<String, String>> dataRequest = response.jsonPath().getList("dataRequests");
but, if i try to get the list of maps of 'value' field:
List<Map<String, String>> dataRequest = response.jsonPath().getList("value");
i get the "null" value. I think it's because i have to wrap it through the whole tree: values - elements - properties and only then value. But it's very complicated and i tried to get it in this way, but obtain only the same result "null".
I noticed that if i print an entrySet of an existing map from list:
List<Map<String, String>> dataRequest = response.jsonPath().getList("dataRequests");
for (Map<String, String> map : dataRequest) {
System.out.println(map.entrySet());
}
I get the result:
[status=success, title=token, values={limit=1, offset=0, count=1, total=1, elements=[{type=DOMAIN, permission=default, properties=[{name=property:id, value=390}, {name=setting:crawler:token, value=someToken}], filters=[]}]}]
And can see value with token there.
Can you prompt me, how can i get the "value" with token either from this List<Map<String, String>> or by other way with deserialitation api?
Your json is kind of complicated with many nested level. I would recommend to use lib jsonpath, instead of using jsonpath provided by rest-assured.
Example:
List<String> values = JsonPath.read(response.toString(), "$..value");
System.out.println(values);
//[390,"token(here's real token)"]
add jsonpath to pom.xml
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.6.0</version>
</dependency>

Using JsonPath in Java (8) to create/add nodes and arrays

I am trying to create or update a JSON with a new key:value nodes inside a JsonArray.
So far I am able to add simple values using a map of nodes, but I am unable to add an array.
The goal is to create a JSON string with the following values:
{
"curfew": [{
"enabled": true,
"lock_time": "00:00",
"unlock_time": "00:10"
},
{
"enabled": true,
"lock_time": "00:20",
"unlock_time": "00:30"
}]
}
Starting from a new and empty JSON and later adding more values (such as the second "curfew" array).
Map<String, Object> values = ImmutableMap.of(
"enabled", true,
"lock_time", "00:00",
"unlock_time", "00:10");
String emptyJson = "{}"; //empty json
DocumentContext doc = getDocument(emptyJson)
doc.set(JsonPath.compile("$.curfew"), values).jsonString();
So far I am getting this (NOT AN ARRAY)
{
"curfew": {
"enabled": true,
"lock_time": "00:00",
"unlock_time": "05:00"
}
}
Create a List<Map<String, Object>> and then add your map in the list
List<Map<String, Object>> list = new ArrayList<>();
list.add(values);
And set the list in doc
doc.set(JsonPath.compile("$.curfew"), list).jsonString();

JSON to Java: How to model lists of objects into generic model

I'm making a spreadSheet using SpreadJS, and I should be able to to add, delete and change the value of a key nested inside many objects. Here is how my json is formatted:
{
"version": "10.0.0",
"sheets": {
"Sheet1": {
"name": "Sheet1",
"data": {
"dataTable": {
"0": {
"0": {
"value": 129
}
}
}
},
"selections": {
"0": {
"row": 0,
"rowCount": 1,
"col": 0,
"colCount": 1
},
"length": 1
},
"theme": "Office",
"index": 0
}
}
}
The data represents, say, the value of each cell in the spreadSheet [0,0], [0,1], [1,1] ...etc. I want to parse this data into a List of generic model, for the field dataTable i would like to represent it like this: Map<Integer, Map<Integer, ValueObj>> for example in this case <0, <0, 129>> but i didn 't find how to do that and how my model would likely be.
I am new to JSON any help is appreciated! Thanks
Then to handle data, you can have a generic class like :
class CellData<T> {
T data;
}
Then read as below :
String jsonInput = "{ \"0\": { \"0\": { \"value\": 129 } } }";
ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<Integer,HashMap<Integer,CellData<Integer>>>> typeRef =
new TypeReference<HashMap<Integer, HashMap<Integer, CellData<Integer>>>>() {};
Map<Integer, Map<Integer, CellData<Integer>>> map = mapper.readValue(jsonInput, typeRef);

How to get specific nodes from a Json Tree without iterating through the entire list

Consider the following Json structure:
{ "ubds": [
{
"id": "33",
"metaData": {
"lineInfo": {
"poNumber": "PO_123",
"poLineNumber": 1
}
},
"confirmedDeliveryDate": "2016-05-26T16:15:51",
"quantity": 99
},
{
"id": "34",
"metaData": {
"lineInfo": {
"poNumber": "PO_123",
"poLineNumber": 2
}
},
"confirmedDeliveryDate": "2016-05-26T16:15:51",
"quantity": 99
},
{
"id": "35",
"metaData": {
"lineInfo": {
"poNumber": "PO_123",
"poLineNumber": 3
}
},
"confirmedDeliveryDate": "2016-05-26T16:15:51",
"quantity": 99
}]}
Using JsonNode, is there a way to get the entire child node {id through quantity} with the poLineNumber attribute value of 3 without having to iterate through all the nodes and returning on a match? Do I need to use JsonPath for this?
You can have a look to JsonPath.
You can first use ObjectMapper to create a Map<String, Object> from the given json string, and read it and evaluate a JsonPath expression. For example:
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> mappedObject = mapper.readValue(jsonString, Map.class);
// Evaluate that expression
Object result = JsonPath.read(mappedObject, "$.ubds[?(#.metaData.lineInfo.poLineNumber==3)]");
or directly read the json string with JsonPath:
Object result = JsonPath.parse(jsonString).read("$.ubds[?(#.metaData.lineInfo.poLineNumber==3)]");

parse Json to Map<String,String>

I have Json response like :
[
{
"first_name": "fname1",
"last_name": "lname1"
},
{
"first_name": "fname2",
"last_name": "lname2",
"city_name": "paris"
},
{
"first_name": "fname2",
"last_name": "lname2",
"city_name": "paris",
"Address": "1st Ave"
}
.
.
.
]
and my fields in JsonObject is dynamic so i can't use a class with predefined fields , so i've decided to use Map to parse the Json response as below :
Collection<List<Map<String,String>>> list_Objects = null;
Reader reader = new InputStreamReader(is);
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<List<Map<String,String>>>>(){}.getType();
list_objects = gson.fromJson(reader, collectionType);
but it throws me this error :
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 1
im not expert in Json parsing so please tell me where is my mistake or if there is another way to implement such behavior i would be very appreciated.
I think the problem is with your Collection wrapper on the List one.
You just need to define the list_Objects as List<Map<String, String>>.
I just tried the following with Jackson's ObjectMapper (which should work the same as GSON) and it worked ok:
List<Map<String, String>> list_objects = objectMapper.readValue(jsonString, new TypeReference<List<Map<String, String>>>(){});
The result is a List of LinkedHashMap objects.
For your GSON example, you just need to remove the Collection<>, or the List<> if you prefer.
If I'm reading this correctly, you're defining your list twice.
Collection<List<Map<String, String>>> would map to a structure like
[ [ {"bla": "bla"}, {"bla": "bla"} ], [ {"foo": "bar"}, ... ], ... ]
(because List is a kind of Collection). So, try using List<Map<String, String>> and see if that works...

Categories