get field list from json object list with Jackson - json

I have JSON data that is getting from api, I want to get list of a field inside of json data.
JSON data :
[
{
"code":"en",
"native":true,
"plurals":{
"length":2,
"forms":[
"one",
"other"
]
}
}, {
"code":"de",
"native":true,
"plurals":{
"length":2,
"forms":[
"one",
"other"
]
}
}, {
"code":"le",
"native":true,
"plurals":{
"length":2,
"forms":[
"one",
"other"
]
}
}
]
I want to get code fields data as list<String> like below :
["en","de","le"]
what is the easiest way to do this?
Note : I am using Spring's RestTemplate to get data.

Use the findValues method to extract the value of all properties named "code":
ObjectMapper om = new ObjectMapper();
JsonNode tree = om.readTree(json);
List<JsonNode> code = tree.findValues("code");
Running it on your example data gives the result
["en", "de", "le"]

Try below method.
public static void main(String[] args) throws JSONException {
String jsonString = jsonResponseFromApi;
JSONObject obj= new JSONObject();
JSONObject jsonObject = obj.fromObject(jsonString);
ArrayList<String> list = new ArrayList<String>();
for(int i=0; i<jsonObject.length(); i++){
list.add(jsonObject.getJSONObject(i).getString("code"));
}
System.out.println(list);
}
}
Refer below thread for more details How to Parse this JSON Response in JAVA

Related

ServiceStack: How do I Serialize a nested object of Dictionary<string, object>?

"event-data":
{
"event": "opened",
"timestamp": 1529006854.329574,
"id": "DACSsAdVSeGpLid7TN03WA",
"delivery-status": {
"title": "success"
}
}
//Structure
public List<Dictionary<string, object>> EventData { get; set; } = new List<Dictionary<string, object>>();
var json = ServiceStack.Text.JsonSerializer.SerializeToString(request.EventData);
So clearly this Jsonifies the object, but only at the root level. Every child object becomes riddled with \n and \t escapes... so it's just flat stringing the children.
What's the proper (Fastest) way to make this just raw nested Json?
You can use the late-bound generic Dictionary<string, object> and List<object>, e.g:
var obj = new Dictionary<string, object> {
["event-data"] = new Dictionary<string, object> {
["event"] = "opened",
["timestamp"] = 1529006854.329574,
["id"] = "DACSsAdVSeGpLid7TN03WA",
["delivery-status"] = new Dictionary<string,object> {
["title"] = "success"
}
}
};
obj.ToJson().IndentJson().Print();
Prints out:
{
"event-data": {
"event": "opened",
"timestamp": 1529006854.329574,
"id": "DACSsAdVSeGpLid7TN03WA",
"delivery-status": {
"title": "success"
}
}
}
When in doubt, you can use JS Utils to parse any arbitrary JSON which will parse them in late-bound generic collections:
var dto = JSON.parse(json);
dto.ToJson().IndentJson().Print();
Note: JS Utils is better at deserializing unknown JSON whilst ServiceStack.Text JSON Serializer is better about deserializing into typed POCOs.

Deserializing JSON objects with variable structure, GSON

I'm trying to deserialize JSON with the following structure using GSON:
"FKeyColumn": [{
"ForeignKeyColumns": {
"Id": "Id"
},
"ReferenceTable": "Expense_Group_Configurations"
}],
"FKeyColumn": [{
"ForeignKeyColumns": {
"Vid": "Id"
},
"ReferenceTable": "Expense_Group_Configurations"
}]
...
I'm not sure how to structure my ForeignKeyColumns class though, since the JSON object it represents contains arbitrary key-value pairings (there's no set structure aside from the object always being named ForeignKeyColumns). How can I parse this with GSON?
It required a custom deserializer for FKeyColumn objects:
public class FKeyColumnDeserializer implements JsonDeserializer<FKeyColumn> {
public FKeyColumn deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
throws JsonParseException {
final JsonArray jsonFKArray = json.getAsJsonArray();
final FKeyColumn fkc = new FKeyColumn();
for (int i = 0; i < jsonFKArray.size(); i++) {
final JsonObject fkObject = (JsonObject) jsonFKArray.get(i);
final String ReferenceTable = fkObject.get("ReferenceTable").getAsString();
final JsonObject ForeignKeyColumns = (JsonObject) fkObject.get("ForeignKeyColumns");
Set<Entry<String, JsonElement>> entrySet = ForeignKeyColumns.entrySet();
for(HashMap.Entry<String, JsonElement> entry : entrySet){
fkc.fkRefTableMap.put(entry.getKey(), ReferenceTable);
}
}
return fkc;
}
}

Extract certain fields and values from request JSON using Jackson

I am looking for a way to include only certain fields from the JSON request received to my service and then log them accordingly to avoid logging too much data.
The fields to include and hence log would be configured in a properties file.
Since I use Spring Boot for my service, Jackson JARs should already be available.
Since the request JSON is complex with nested arrays and objects as fields am not sure if I can achieve my requirement with Jackson.
Is there a way to extract only certain fields along with their values from a input request JSON using the Jackson API?
Basically, I am looking at 2 use cases.
1.Select one or more elements (which I intend to pass by config) from Json String and then render them
2.Select and update one or more elements inline. I want to mask the values of the elements before rendering them.
I am providing the code for selecting the element and Json which I used along with what I expect as below.
public String getValues(String key,String jsonString){
String fieldNodeStr =null;
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(jsonString);
JsonNode fieldNode = node.at(key);
fieldNodeStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(fieldNode);
System.out.println(fieldNodeStr);
} catch (IOException e) {
System.out.println("IOException:",e);
}catch (Exception e) {
System.out.println("Exception:",e);
}
}
My Json is as below,
{
"employeeId" : "5353",
"salesId" : "sales005",
"manager" : {
"userId" : "managerUser",
"isSuperUser" : false,
"firstName":"manager first name",
"lastName":"manager last name"
},
"administrator" : {
"userId" : "administratorUser",
"isSuperUser" : false,
"firstName":"admin first name",
"lastName":"admin last name"
},
"requester" : [
{
"id":"1234",
"demographic" : {
"firstName" : "hello",
"lastName" : "hai"
}
},
{
"id":"1235",
"demographic" : {
"firstName" : "welcome",
"lastName" : "user"
}
}
]
}
I have 2 issues as below.
If I pass "/manager/userId" ,"/administrator/isSuperUser" (OR) "/salesId" I am able to get the expected value.
But, If want to get the /requester/id (OR) /requester/demographic (OR) /requester/demographic/lastName , I am not able to fetch.
I am getting null values.
I expect the following when I pass , "/requester/id" (OR) "/requester/demographic" respectively.
"requester" : [
{
"id":"1234"
},
{
"id":"1235"
}
]
"requester" : [
{
"demographic" : {
"firstName" : "hello",
"lastName" : "hai"
}
},
{
"demographic" : {
"firstName" : "welcome",
"lastName" : "user"
}
}
]
Along with fetch I also want to update the values inline after locating them with JsonPointer
I have my code as below for the updation,
public String findAndUpdate(String key,String jsonString,String repValue){
String fieldNodeStr =null;
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(jsonString);
JsonNode fieldNode = node.at(key);
//Update the value of located node to a different one
((ObjectNode) fieldNode).put(key,repValue);
fieldNodeStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(fieldNode);
System.out.println(fieldNodeStr);
} catch (IOException e) {
System.out.println("IOException:",e);
}catch (Exception e) {
System.out.println("Exception:",e);
}
return fieldNodeStr;
}
When I pass, "/manager/userId" as value of key, I get the below error,
17:21:24.829 [main] ERROR com.demo.jsondemo.TestClass - Exception:
java.lang.ClassCastException: com.fasterxml.jackson.databind.node.TextNode cannot be cast to com.fasterxml.jackson.databind.node.ObjectNode
at com.demo.jsondemo.TestClass.findAndUpdate(TestClass.java:95) [classes/:na]
at com.demo.jsondemo.TestClass.main(TestClass.java:221) [classes/:na]
JSON Pointer
You could use JSON Pointer (a string syntax for identifying a specific value within a JSON document) defined by the RFC 6901.
For example purposes, consider the following JSON:
{
"firstName": "John",
"lastName": "Doe",
"address": {
"street": "21 2nd Street",
"city": "New York",
"postalCode": "10021-3100",
"coordinates": {
"latitude": 40.7250387,
"longitude": -73.9932568
}
}
}
To query the coordinates node, you could use the following JSON Pointer expression:
/address/coordinates
JSON Pointer and Jackson
Jackson 2.3.0 introduced support to JSON Pointer and it can be used as following:
String json = "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"address\":{\"street\":"
+ "\"21 2nd Street\",\"city\":\"New York\",\"postalCode\":\"10021-3100\","
+ "\"coordinates\":{\"latitude\":40.7250387,\"longitude\":-73.9932568}}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(json);
JsonNode coordinatesNode = node.at("/address/coordinates");
The coordinates node could be parsed into a bean:
Coordinates coordinates = mapper.treeToValue(coordinatesNode, Coordinates.class);
Or can be written as String:
String coordinatesNodeAsString = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(coordinatesNode);
Jayway JsonPath
A good alternative to JSON Pointer is JSONPath. In Java, there's an implementation called Jayway JsonPath, which integrates with Jackson.
To query the coordinates node with JsonPath, you would use the following expression:
$.address.coordinates
And the code to query the node would be like:
JsonNode coordinatesNode = JsonPath.parse(json)
.read("$.address.coordinates", JsonNode.class);
JsonPath requires the following dependency:
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.2.0</version>
</dependency>
And, to integrate with Jackson, following lines are required:
Configuration.setDefaults(new Configuration.Defaults() {
private final JsonProvider jsonProvider = new JacksonJsonProvider();
private final MappingProvider mappingProvider = new JacksonMappingProvider();
#Override
public JsonProvider jsonProvider() {
return jsonProvider;
}
#Override
public MappingProvider mappingProvider() {
return mappingProvider;
}
#Override
public Set<Option> options() {
return EnumSet.noneOf(Option.class);
}
});
Update based on your requirements
Based on the additional details you have provided in your question, I would say JSONPath will offer you more flexibility the JSON Pointer.
You can try the following:
Instead of /requester/id, use $.requester[*].id.
Instead of /requester/demographic, use $.requester[*].demographic.
These expressions can be tested online. Have a look at the following resources:
JSONPath Online Evaluator
JSONPath Expression Tester
And read the Jayway JsonPath documentation to understand how to use it properly.
Jackson's JsonView annotations should allow you to mark certain fields/getters with a particular view. Something like the following should work.
public class Item {
public static class LoggingView {}
#JsonView(LoggingView.class)
public int id;
#JsonView(LoggingView.class)
public String name;
public byte[] data;
}
This should allow you to write id and name without writing data by doing the following:
public class Something {
private static final Logger logger = LoggerFactory.getLogger();
private static final ObjectWriter loggingItemWriter = new ObjectMapper().writerWithView(Item.LoggingView.class);
public void doSomething(Item item) {
...
logger.info(loggingItemWriter.writeValueAsString(item));
...
}
}

depending on input json array return output json in literal json in spring mvc

My controller
#Controller
public class HomeController {
#RequestMapping(value = "/trans", method = RequestMethod.POST)
public #ResponseBody String jsontest(#RequestBody String transjson) throws JsonProcessingException, IOException, JSONException {
try{
JsonParser parser = new JsonParser();
parser.parse(transjson);
String output = null;
JSONObject obj1 = new JSONObject(transjson);
int size=obj1.getJSONArray("inArray").length();
/* this is where I need help.*/
for(int i=0;i<size;i++){
output="{\"outArray\":[{\"in\":\""+obj1.getJSONArray("inArray").get(i)+"\",\"out\":\"hie\"}]}";
}
return output;
}
catch(JsonSyntaxException ex)
{
System.out.println(ex.getMessage());
return "{\"message\":\"Invalid JSON\"}";
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
return "{\"message\":\"Exception occured\"}";
}
}
}
what I want is if my input JSON is
{
"inArray": [
"first"
]
}
then my output should be
{
"outArray": [
{
"in": "first",
"out": "hie"
}
]
}
if my input JSON is
{
"inArray": [
"first",
"second"
]
}
then my output should be
{
"outArray": [
{
"in": "first",
"out": "hie"
},
{
"in": "second",
"out": "hie"
}
]
}
means I don't know the number of the elements in the input array in the input json. And i need make my output in the literal json format on the basis of input elemen numbers as shown above.
I tried few things but have not been able to get the desired output.
I have been able to do this.
Actually I was trying to make string object but instead of that if I make jsonobject and put everything in it and at last return that jsonobject.tostring() form then the desired resultcan be obtained.
int size=obj1.getJSONArray("inArray").length();
JSONArray ja = new JSONArray();
for(int i=0;i<size;i++){
JSONObject jo = new JSONObject();
jo.put("in", obj1.getJSONArray("inArray").get(i));
jo.put("out", "hie");
ja.put(jo);
}
JSONObject mainObj = new JSONObject();
mainObj.put("outArray", ja);
return mainObj.toString();

Deserialize json array and extract value using rest assured

I am a java, json, rest assured newbie and trying to work and learn how to test a rest api. I have an array returned as a rest assured response:
Response response = given(getProjectInfoRequest).get();
response.asString();
{
"options": [
{
"text": "111",
"label": "ABC"
},
{
"text": "222",
"label": "DEF"
},
{
"text": "333",
"label": "GHI"
}
]
}
and I want to extract the value of text say for label value as "DEF", how I can do that?
Please note I have done below so far after reading through so many posts:
1. Options[] options = given(getProjectInfoRequest).when().get().as(Options[].class);
this was giving me exception :
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
then I tried below:
2. Options options = gson.fromJson(response.asString(), Options.getClass());
this at least resolved the above issue.
public class Options {
public String getLabel() {
return label
}
public void setLabel(String label) {
this.label = label
}
public String getValue() {
return value
}
public void setValue(String value) {
this.value = value
}
public String label;
public String value;
}
From this point I am not sure how I can iterate through the array of text and values to extract what I need, please can you guys provide your inputs?
Please pardon my ignorance for asking such a basic question.
Please also suggest me a good source/way to learn this too.
Thanks in advance!
U can use Gson - This is a Java library that can be used to convert Java Objects into their JSON representation.
JsonParser parser = new JsonParser();
JsonObject o = (JsonObject)parser.parse(response.asString());
for (Map.Entry<String,JsonElement> entry : o.entrySet()) {
JsonArray array = entry.getValue().getAsJsonArray();
for (JsonElement elementJSON : array) {
[...]
}
}