How to get json value with jackson? - java

String url = "https://ko.wikipedia.org/w/api.php?action=query&format=json&list=search&srprop=sectiontitle&srlimit=1&srsearch=grand-theft-auto-v";
String test = restTemplate.getForObject(url, String.class);
Map<String, String> testToJson = objectMapper.readValue(test, Map.class);
testToJson is:
{
batchcomplete: "",
continue: {
sroffset: 1,
continue: "-||",
},
query: {
searchinfo: {
totalhits: 12
},
search: [
{
ns: 0,
title: "그랜드 테프트 오토 V",
pageid: 797633,
}
],
},
}
I want to get title value.
I try
testToJson.get("title")
but it returns null.
How to get title value with jackson?

You can deserialise it to a JsonNode and use JSON Pointer to get required field:
JsonNode node = mapper.readValue(jsonFile, JsonNode.class);
String title = node.at("/query/search/0/title").asText();

you could build a class for this json result then read from it.
public class Result {
private JsonNode searchinfo;
private JsonNode[] searches;
}
// then read:
Result testToJson = objectMapper.readValue(test, Result.class);
System.out.println(testToJson.getSearches(0).get("title"));
refer

It is impossible to read JSON into an instance of a generic class like that because the info about generics are used in compile time and already lost when program is running.
Jackson captures the data about generics using a sub-classed instance of TypeReference<T>.
Map<String, String> testToJson = objectMapper.readValue(test, new TypeReference<Map<String, String>>(){});
The problem with this approach is that Map<String, String> almost never describes complex data (like in the example) correctly. The example contains not only string values, there are numbers and even nested objects.
In situations like that, when you don't want or cannot write a class that describes the structure of the JSON, the better choice is parsing the JSON into a tree structure and traverse it. For example:
JsonNode node = objectMapper.readTree(test);
String title = node.get("query").get("search").get(0).get("title").asText();
Integer offset = node.get("continue").get("strOffset").asInt()

Related

Simplest way to convert this array in to the specified one using Java

I have this String Json Payload
[
"key1":{
"atr1":"key1",
"atr2":"value1",
"atr3":"value2",
"atr4":"value3,
"atr5":"value4"
},
"key2":{
"atr1":"key2",
"atr2":"value5",
"atr3":"value6",
"atr4":value7,
"atr5":"value8"
}
]
and I want it to be converted in to the following format using Java
[
{
"atr2":"value1",
"atr3":"value2",
"atr4":"value3,
"atr5":"value4"
},
{
"atr2":"value5",
"atr3":"value6",
"atr4": "value7",
"atr5":"value8"
}
]
What would be the simplest way of transforming this ?
You cannot, because the example below is not valid json.
Check it out using this JSON validator.
If you paste this in (I've fixed some basic errors with lack of quotes)
{
{
"atr2":"value1",
"atr3":"value2",
"atr4":"value3",
"atr5":"value4"
},
{
"atr2":"value5",
"atr3":"value6",
"atr4":"value7",
"atr5":"value8"
}
}
You will get these errors ...
It can work if you change the target schema to something like this by using a json-array to contain your data.
[
{
"atr2":"value1",
"atr3":"value2",
"atr4":"value3",
"atr5":"value4"
},
{
"atr2":"value5",
"atr3":"value6",
"atr4":"value7",
"atr5":"value8"
}
]
If this works for you, then this problem can easily be solved by using the ObjectMapper class.
You use it to deserealize the original JSON into a class, which has two fields "key1" and "key2"
Extract the values of these fields and then just store them in an array ...
Serialize the array using the ObjectMapper.
Here a link, which explains how to use the ObjectMapper class to achieve the goals above.
EDIT:
So you'll need the following classes to solve the problem ...
Stores the object data
class MyClass {
String atr2;
String art3;
}
Then you have a container class, which is used to store the initial json.
class MyClassContainer {
MyClass key1;
MyClass key2;
}
Here's how you do the parse from the original json to MyClassContainer
var mapper = new ObjectMapper()
var json = //Get the json String somehow
var myClassContainer = mapper.readValue(json,MyClassContainer.class)
var mc1 = myClassContainer.getKey1();
var mc2 = myClassContainer.getKey2();
var myArray = {key1, key2}
var resultJson = mapper.writeValueAsString(myArray)
Assuming that you will correct the JSON into a valid one (which involves replacing the surrounding square braces with curly ones, and correct enclosure of attribute values within quotes), here's a simpler way which involves only a few lines of core logic.
try{
ObjectMapper mapper = new ObjectMapper();
mapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
HashMap<String, Data> map = mapper.readValue( jsonString, new TypeReference<HashMap<String, Data>>(){} );
String json = mapper.writeValueAsString( map.values() );
System.out.println( json );
}
catch( JsonProcessingException e ){
e.printStackTrace();
}
jsonString above is your original JSON corrected and valid JSON input.
Also notice the setting of FAIL_ON_UNKNOWN_PROPERTIES to false to allow atr1 to be ignored while deserializing into Data.
Since we are completely throwing away attr1 and its value, the Data class will represent all fields apart from that.
private static class Data{
private String atr2;
private String atr3;
private String atr4;
private String atr5;
}

how to update the json with map values using java?

I have below json:
{
"type":Flowers,
"input_data": [
{
"id": 35742,
"Request_ID": 8383,
"data_line": "*****Sample text here*****",
"variety": {
"Rose": 0,
"Jasmine": 0,
"Lily": 1,
"Sunflower": 1,
},
"responded": 1
},
{
"id": 35992,
"Request_ID": 8983,
"data_line": "*****Sample text here*****",
"variety": {
"Rose": 1,
"Jasmine": 0,
"Lily": 0,
"Sunflower": 1,
},
"responded": 1
}
],
"token": "F9500930C-15A6-4111-AD7F-7D0DF0CEE4D8"
}
How do I map the values in "variety" with "id"?
Note: id is coming from the response of a different API which should be replaced in this json and mapped with variety.
It's not a good idea to have a field like 'input_data' in your json.
Try to redo your json that's aligned to your data model and something that can be mapped to Java objects.
GSON is a great library for dealing with JSONs in Java - https://github.com/google/gson
I can give you a utility method to get a list of Java objects from a json reprenstation like this:
private static Type typeOfT = TypeToken.getParameterized(List.class, <<your-class>>.class).getType();
public static <T> List<T> loadListFromFile(String fileName, Class<T> clazz) throws Exception{
File file = new File(fileName);
String json = new String(Files.readAllBytes(file.toPath()));
return gson().fromJson(json, typeOfT);
}
First, your JSON string is invalid (e.g. Flowers should be quoted by double quotes). Second, I am confused about what you really want. Therefore, according to the comment under your question, you said that you need a mapping between id and variety. Here comes one way to achieve that by following steps with Jackson (One of the most popular JSON libraries.).
Step 1
Create nested POJOs for deserialization.
class Result {
#JsonProperty("input_data")
private List<InputData> inputData;
//general getter and setter
}
class InputData {
private int id;
private Variety variety;
//general getters and setters
}
class Variety {
#JsonProperty("Rose")
private int rose;
#JsonProperty("Jasmine")
private int jasmine;
#JsonProperty("Lily")
private int lily;
#JsonProperty("Sunflower")
private int sunflower;
//general getters, setters and toString()
}
Step 2
Deserialize JSON response to Result and transform the InputData into Map<Integer, Variety> with Java 8.
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Result result = mapper.readValue(jsonStr, Result.class);
Map<Integer, Variety> idVarietyMap = result.getInputData().stream()
.collect(Collectors.toMap(InputData::getId, InputData::getVariety));
System.out.println(idVarietyMap.toString());
Console output
{35992=Variety [rose=1, jasmine=0, lily=0, sunflower=1], 35742=Variety [rose=0, jasmine=0, lily=1, sunflower=1]}

Read single value from nested object using Gson in Java

Below is my Json. I want to get the value of "Id" inside "Details" using Gson
{
"name": "testAutomation-1",
"owner": "TestUSer",
"description": "testAutomation-1",
"subSet": [
"test-audit"
],
"labels": "{\"engagementType\":\"Sx\",\"type\":\"collect\"}",
"createdTime": 1548508294790,
"updatedTime": 1548654725381,
"scheduleDateTime": null,
"timeZone": null,
"jobStatus": "Report-Requested",
"loggedInUser": null,
"Details": [
{
"Status": "Completed",
"Id": "fe1f6b40-216b-11e9-a769-25be4c5889e7"
}
]
}
I created a map using the below code. But not sure how to get the value
Map<String, Object> createmap = new HashMap<String, Object>();
Gson gson = new Gson();
Type type = new TypeToken<Map<String, Object>>(){}.getType();
createmap = gson.fromJson(jsonobj.toString(), type);
Assuming that you need the first element of the array, you could do something like this (knowing that DATA is the JSon String you provided):
Map<String, JsonElement> resultMap;
Gson gson = new Gson();
Type type = new TypeToken<Map<String, JsonElement>>() {}.getType();
JsonElement jsonElement = gson.fromJson(DATA, JsonElement.class);
resultMap = gson.fromJson(jsonElement.toString(), type);
JsonArray details = resultMap.get("Details").getAsJsonArray();
JsonObject recordElement = details.get(0).getAsJsonObject();
System.out.println(recordElement.get("Id").getAsString());
All this does is fetch the Details array as a JsonArray and it fetches the value of the Id element afterwards.
Since you seem to be dealing with a UUID, you could maybe benefit from using:
UUID uuid = UUID.fromString(recordElement.get("Id").getAsString());
As per Gson guide, you need to use the correct parameterized type instead of your generic type. Then you can easily access the value you need from the map.
Map<String, Dummy> map = new HashMap<String, Dummy>();
Type t = new TypeToken<Map<String, Dummy>>() {}.getType();
map = new Gson().fromJson(jsonobj.toString(), type);
Then you can get the map value (map.get("details") and read the id from that.
In your JSON Details is a list or an array. So there is not just one id in some cases and you should prepare for that also.
It is usually also a good habit to create DTOs to describe data, so like two below classes:
Data
#Getter
public class Data {
// Recommendation, in Java field name should start lower case
#SerializedName("Details")
List<Detail> details; // Could be some List also
}
Detail
#Getter
public class Detail {
// Recommendation, in Java field name should start lower case
#SerializedName("Id")
private UUID id;
}
This also allows later to flexibly pick up any other fields you need from the same JSON.
Serialize your JSON like:
Data data = gson.fromJson(YOUR_JSON, Data.class);
Check the ids - for example - like:
data.getDetails().forEach(d -> log.info("{}", d.getId()));

represent JSON file in a java program for querying values by key

I want to represent this file in my java program.
What I want to do is quickly search through it by "key" value, so for instance, given the value P26 I'd want to return spouse.
Maybe I can read it in as a HashMap using gson as I did with this program.
But what to do about this wonky structure:
{
"properties": {
"P6": "head of government",
"P7": "brother",
...
How could I fit that well into a HashMap? Is HashMap even the best choice?
I've sort of simplified it to this:
{
"P6": "head of government",
"P7": "brother",
"P9": "sister",
"P10": "video",
"P14": "highway marker",
"P15": "road map",
"P16": "highway system",
"P17": "country",
"P18": "image",
I've tried to use this code, but it outputs null
/*
* P values file
*/
String jsonTxt_P = null;
File P_Value_file = new File("properties-es.json");
//read in the P values
if (P_Value_file.exists())
{
InputStream is = new FileInputStream("properties-es.json");
jsonTxt_P = IOUtils.toString(is);
}
Gson gson = new Gson();
Type stringStringMap = new TypeToken<Map<String, String>>(){}.getType();
Map<String,String> map = gson.fromJson(jsonTxt_P, stringStringMap);
System.out.println(map);
It doesn't work because that file is not a Map<String, String>. it has a properties element, which contains a mapping, and a missing element, which contains an array. This mismatch will cause Json to return null, which is what you're seeing. Instead, try doing this:
public class MyData {
Map<String, String> properties;
List<String> missing;
}
And then, to deserialize, do:
MyData data = gson.fromJson(jsonTxt_P, MyData.class);
Map<String, String> stringStringMap = data.properties;
This will make the data structure match the structure of the json, and allow json to properly deserialize.

Is there a generic way of parsing Json in Java?

I have tried with gson and Jackson parsers unfortunately I couldn't achieve what I wanted to.
{
"rateName": "My Special Rate",
"adjustments": [
{
"adjustmentType": "LOAN_AMOUNT_GREATER_THAN_550K",
"rate": 0.75
},
{
"adjustmentType": "AMORTIZATION_TERM_LESS_THAN_30_YEARS",
"rate": -0.2
}
],
"errorTypes": [],
"premiumTaxs": [],
"renewalPremiums": [],
"totalInitialRate": 1.95,
"optimumPricing": false,
"miPricingVO": null,
"rateCardId": "BALS_NR",
"ratingInfoBaseRate": 1.4
}
Above is the Json I want to parse. I want to create generic methods using which I can access a value by name easily. For example:
getName(rateName) - Should return 'My Special Rate'
getNameFromArray(adjustmentType, adjustments) - Should return
'LOAN_AMOUNT_GREATER_THAN_550K'
Is there a way to do this? It should be generic so that this can be applied on any Json file.
Additional info: I tried using Gson, but this parses the whole file and throws an error if it finds an array.
JsonReader j = new JsonReader(new FileReader("Path of Json"));
j.beginObject();
while (j.hasNext()) {
String name = j.nextName();
if (name.equals("rateName")) {
System.out.println(j.nextString());
}
System.out.println(name);
}
I tried with jackson and encountered the same as Gson.
JsonFactory jfactory = new JsonFactory();
JsonParser jParser = jfactory.createJsonParser("Path of Json");
while (jParser.nextToken() != JsonToken.END_OBJECT) {
System.out.println(jParser.getCurrentName());;
}
If you mean standard library when you say generic, then org.json would be that library.
Altough not as intuitive as GSON or Jackson, it is easy to use it:
JSONObject jsonData = new JSONObject(jsonString);
String rateName= jsonData.getString("rateName");//My Special Rate
To parse array you need to loop:
JSONArray adjustments = jsonData.getJSONArray("adjustments");
for(int i = 0; i < adjustments.length(); i++){
JSONObject adjustment = adjustments.getJSONObject(i);
String adjustmentType = adjustment.getString("adjustmentType");
}
Hi You can use JASON READER , it readers the JSON and map the data into a MAP .
Below is the URL to Download the JAR JASON READER.
https://drive.google.com/open?id=0BwyOcFBoJ5pueXdadFFMS2tjLVU
Below is the example -
package com;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.JasonReader;
public class Test {
public static void main(String[] args) {
String request ="{\"rateName\": \"My Special Rate\",\"adjustments\":[{\"adjustmentType\": \"LOAN_AMOUNT_GREATER_THAN_550K\",\"rate\": 0.75},{\"adjustmentType\": \"AMORTIZATION_TERM_LESS_THAN_30_YEARS\",\"rate\": -0.2}],\"errorTypes\": [],\"premiumTaxs\": [],\"renewalPremiums\": [],\"totalInitialRate\": 1.95,\"optimumPricing\": false,\"miPricingVO\": null,\"rateCardId\": \"BALS_NR\",\"ratingInfoBaseRate\": 1.}";
//
Map<String,String> map =new HashMap<String,String>();
map=JasonReader.readJason(request,map);
//System.out.println(map);
for (Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey()+ "=" +entry.getValue());
}
}
}
OUTPUT -
rateCardId=BALS_NR
adjustments|rate1=-0.2
miPricingVO=null
adjustments|adjustmentType=LOAN_AMOUNT_GREATER_THAN_550K
adjustments|adjustmentType1=AMORTIZATION_TERM_LESS_THAN_30_YEARS
adjustments|rate=0.75
optimumPricing=false
totalInitialRate=1.95
rateName=My Special Rate
ratingInfoBaseRate=1.
You can use the standard JsonParser which is part of the javax.json package. This parser is part of Java EE since version 7 and you can use this parser without any additional library.
The parser allows you to navigate through a JSON structure using the so called 'pull parsing programming model'
JsonParser parser = Json.createParser(myJSON);
Event event = parser.next(); // START_OBJECT
event = parser.next(); // KEY_NAME
String key = parser.getString(); // 'rateName'
event = parser.next(); // STRING_VALUE
String value=parser.getString(); // 'My Special Rate'
event = parser.next(); // START_ARRAY
....
But of course you need to navigate through your json data structure
Or you can just use Jodd JSON parser. You just need to deserialize the input string and the result will be collected in regular Map and List.
JsonParser jsonParser = new JsonParser();
Map<String, Object> map = jsonParser.parse(input);
Simple as that - and the result is the most generic as it can be. Then just call map.get("rateName") to get your value and so on.
But notice that for adjustments you can get the way you want without some util method that would iterate elements and search for the right one. If you can, change the JSON so that you dont have an array of adjustments, but a map.
If you need specific results, just pass the type with the input string. See more about parsing features.

Categories