how to parse given data into a java object - java

I want to parse below given data in to some java object, but I am not able to parse. String is as follows -
{\"objectsTree\":\"{\"Address\":[],\"Customer\":[\"Address\"]}\",\"objectsSequence\":\"[\"Customer\",\"Address\"]\"}
I have tried parsing this into HashMap and HashMap
but this is returning malformed JSON exception, and that is making sense, because of too many double quotes objects are ending abruptly. I want to parse this as follows-
{
"objectsTree":"{"Address":[],"Customer":["Address"]}",
"objectsSequence":"["Customer","Address"]"
}
here you can see that objectsTree is one object against one string and objectSequence is another. to be specific object tree is supposed to be a treemap , object sequence is supposed to be a ArrayList.
Any Idea how should I proceed.
code update-
package org.syncoms.backofficesuite.controller;
import java.util.HashMap;
import com.google.gson.Gson;
public class Test {
public static void main(String[] args) {
//String json = "{\"Success\":true,\"Message\":\"Invalid access token.\"}";
String json ="{\"objectsTree\":\"{\"Address\":[],\"Customer\":[\"Address\"]}\",\"objectsSequence\":\"[\"Customer\",\"Address\"]\"}";
Gson jsonParser = new Gson();
#SuppressWarnings("unchecked")
HashMap<String,Object> jo = (HashMap<String,Object>) jsonParser.fromJson(json, HashMap.class);
System.out.println(jo);
//Assert.assertNotNull(jo);
//Assert.assertTrue(jo.get("Success").getAsString());
}
}
the error which I am getting -
Exception in thread "main" com.google.gson.JsonParseException: Failed parsing JSON source: java.io.StringReader#201644c9 to Json
at com.google.gson.JsonParser.parse(JsonParser.java:59)
at com.google.gson.Gson.fromJson(Gson.java:443)
at com.google.gson.Gson.fromJson(Gson.java:396)
at com.google.gson.Gson.fromJson(Gson.java:372)
at org.syncoms.backofficesuite.controller.Test.main(Test.java:16)
Caused by: com.google.gson.ParseException: Encountered " <IDENTIFIER_SANS_EXPONENT> "Address "" at line 1, column 19.
Was expecting one of:
"}" ...
"," ...

The main issue here is that the input is simply not a valid JSON String, and no JSON parser is going to accept it. the doulbe qoutes have to be escaped.
a Valid JSON String is as follows:
String jsonInput = "{\"objectsTree\":\"{\\\"Address\\\":[],\\\"Customer\\\":[\\\"Address\\\"]}\",\"objectsSequence\":\"[\\\"Customer\\\",\\\"Address\\\"]\"}";
and this can be parsed using, for instance, Jackson:
ObjectMapper om = new ObjectMapper();
TypeFactory tf = om.getTypeFactory();
JavaType mapType = tf.constructMapType(HashMap.class, String.class, String.class);
Map<String, String> map = (Map<String, String>)om.readValue(jsonInput, mapType);
System.out.println(map);
Printout is:
{objectsSequence=["Customer","Address"], objectsTree={"Address":[],"Customer":["Address"]}}

There are multiple ways you could do that.
Firstly, if your data has always the same format you can simply create some methods which will create your TreeMap and ArrayList as required. You can do everything you want with String.replace(), StringTokenizer, matcher pattern. You can split your data into tokens and based on your needs place them in your required data structure. I find this way quite efficient and once you get to know better how to parse data and extract what you need, you can use this in many other examples.
If your data is formatted in JSON then there might be even easier ways of parsing it.You can decode it as Java object quite easy.

JSON string is not well formed one. Try as below
{
"objectsTree":{"Address":[],"Customer":["Address"]},
"objectsSequence":["Customer","Address"]
}
JSON key is always string &
JSON values can be:
•A number (integer or floating point)
•A string (in double quotes)
•A Boolean (true or false)
•An array (in square brackets)
•An object (in curly braces)
•null.
See the below code with well formed string and its output
String a = "{\r\n" +
"\"objectsTree\":{\"Address\":[],\"Customer\":[\"Address\"]},\r\n" +
"\"objectsSequence\":[\"Customer\",\"Address\"]\r\n" +
"}";
ObjectMapper mapper = new ObjectMapper();
HashMap<String,Object> jo = (HashMap<String,Object>) mapper.readValue(a, HashMap.class);
System.out.println("result: "+ jo);
result: {objectsTree={Address=[], Customer=[Address]}, objectsSequence=[Customer, Address]}
with your json string
String json ="{\"objectsTree\":\"{\"Address\":[],\"Customer\":[\"Address\"]}\",\"objectsSequence\":\"[\"Customer\",\"Address\"]\"}";
ObjectMapper mapper = new ObjectMapper();
HashMap<String,Object> jo = (HashMap<String,Object>) mapper.readValue(json, HashMap.class);
System.out.println("result: "+ jo);
error :
Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('A' (code 65)): was expecting comma to separate OBJECT entries
at [Source: java.io.StringReader#77d2b01b; line: 1, column: 20]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:943)
In your json string, for key objectsTree, the value is started with \" and its matching \" is closed before string Address. This is causing the parse error.
"{\"Address
The other two answers also saying that your json string is in invalid format.
I also added the supported json values for your reference.
If you change to correct format, any json parser will work,

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 get json value with jackson?

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()

Getting null pointer exception while converting JSON String to List using ObjectMapper

I have a JSON string which is a list of String
String jsonString = "['String1','String2','String3']";
I am trying to convert it into a List
List<String> list = new ObjectMapper().readValue(jsonString, List.class);
But it is giving me java.lang.NullPointerException
Can any one help me in finding out what is wrong with it?
Edit 2 : Keeping the original post and removing things which may confuse others.
String jsonString = "['String1','String2','String3']"; is not JSON format.
Tried with double quotes ?
String jsonString = "[\"String1\",\"String2\",\"String3\"]";
List<?> list = new ObjectMapper().readValue(jsonString, List.class);
Simple quote is not valid

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.

How to append a String to JSON String in java?

I am getting the data from the Zookeeper node like this
byte[] bytes = client.getData().forPath("/my/example/node1");
String ss = new String(bytes);
Here ss will have data like this which is a simple JSON String consisting of key value pair -
{"description":"Some Text", "machinename":"machineA", "ipaddress":"192.128.0.0"}
Now I want to append one more key value pair at the end to the above JSON String. This is the below key value pair I want to append -
"version":"v3"
So the final JSON String will look like this -
{"description":"Some Text", "machinename":"machineA", "ipaddress":"192.128.0.0", "version":"v3"}
What's the best and efficient way to do this?
Use a JSON Parser/Generator to parse your given JSON to a tree structure and then add your JSON field.
With Gson, that would look something like this
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(ss, JsonObject.class); // parse
jsonObject.addProperty("version", "v3"); // modify
System.out.println(jsonObject); // generate
prints
{"description":"Some Text","machinename":"machineA","ipaddress":"192.128.0.0","version":"v3"}
Will Zookeeper always return valid JSON or their custom format? Be aware of that.
When it comes to JSON processing, string manipulation only works in special and simple cases. For the general case, a good JSON parser library should be used.
Jackson is among the top of such libraries in terms of performance, efficiency, versatility and reliability, plus it is published under the commercial-friendly Apache 2.0 license.
Following is a simple implementation of the requested answer in Jackson.
public static void main(String[] args)
{
String ss = "{\"description\":\"Some Text\", \"machinename\":\"machineA\", \"ipaddress\":\"192.128.0.0\"}";
System.out.println("JSON string before: " + ss);
try
{
ObjectMapper mapper = new ObjectMapper();
Map<String, String> map = (Map<String, String>)mapper.readValue(ss, Map.class);
map.put("version", "v3");
ss = mapper.writeValueAsString(map);
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("JSON string after: " + ss);
}
Basic string manipulation. Insert your additional string before the final close brace }. Make sure to add a comma.
Json objects don't need to be ordered.
String json = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
String json2 = "\"version\":\"v3\"";
json2 = ',' + json2;
String json3 = json.substring(0,json.length()-1) + json2 + json.charAt(json.length()-1);
That should be the simplest, most efficient way, if that's all you need to do.
For additional reading on String manipulation,
http://docs.oracle.com/javase/tutorial/java/data/manipstrings.html

Categories