How do I parse this JSON string using GSON in servlet - java

How can I parse this JSON string to create collection object in servlet
{"title":["1","2"],"amount":["1","3"]}
inner class in my servlet
public class Data {
private List<String> title;
private List<String> amount;
//getters and setters
}
parsing json
Gson gson = new Gson();
String param=request.getParameter("info");
Data data = gson.fromJson(param, Data.class);
List<String> a=data.getTitle();
if(a==null){p("a null");}else{p("a not null");} //here a is null, prints "a null"
here is the jsfiddle of how I am creating the json string http://jsfiddle.net/testtracker/XDNLp/
client side in form submit function
var dataString=JSON.stringify($(this).serializeObject());
$.ajax({
type: "POST",
url: URL,
data: {"info":JSON.stringify($(this).serializeObject())},
success: function(data){
}
});
This is what I have till now. am I on correct way? what next should I do to System.print them?

When I am unable to solve something, I write the smallest possible program to verify my understanding is correct. In your case, I came up with this:
import java.util.List;
import com.google.gson.Gson;
public class GsonTest {
public static class Data {
private List<String> title;
public List<String> getTitle() {return title;}
public Data() {}
}
public static void main (String [] args) {
Gson gson = new Gson();
Data data = gson.fromJson("{\"title\":[\"1\",\"2\"]}", Data.class);
System.out.println(data.getTitle());
}
}
Compiled, and ran, and it outputs:
["1", "2"]
So I still believe that the input that the servlet receives, is not correct (or you have not provided an accurate description of your existing code). Please compare the example above, against your real code.

try
public class Data {
private ArrayList<String> title;
private ArrayList<String> amount;
//getters and setters
}
List is a abstract class (So GSON doesn't know how to create it)

Related

Java parse all values from Array in JSON to ArrayList

I have a problem. I have the following JSON:
{
"Market":"USDT",
"Coin":"BTC",
"Period":"1h",
"EmergencyPerc":-25,
"TakeProfitPerc":1.2,
"ProtectiveOrdersEnabled":"no",
"EMACrossMarginPerc":0.5,
"EMABuySellPeriod":"15m",
"EMABuySellNameLow":"EMA10",
"EMABuySellNameHigh":"EMA50",
"EMAUnfreezePeriod":"1h",
"EMAUnfreezeNameLow":"EMA20",
"EMAUnfreezeNameHigh":"EMA200",
"SimTemplate":"t001",
"Patterns":{
"Buy":[
"buy_pattern_1",
"buy_pattern_2"
],
"Sell":[
"sell_pattern_1",
"sell_pattern_2"
]
}
}
I want to parse that JSON to the following class:
public class AgentStrategy {
private String Market;
private String Coin;
private double EmergencyPerc;
private double TakeProfitPerc;
private String ProtectiveOrdersEnabled;
public double EMACrossMarginPerc;
public String EMABuySellPeriod;
public String EMABuySellNameLow;
public String EMABuySellNameHigh;
public String EMAUnfreezePeriod;
public String EMAUnfreezeNameLow;
public String EMAUnfreezeNameHigh;
private String SimTemplate;
private ArrayList<PriceDropSell> PriceDropSells;
private ArrayList<String> buyPatternsUsed = new ArrayList<>();
private ArrayList<String> sellPatternsUsed = new ArrayList<>();
}
For that I have the following method inside that class:
public AgentStrategy parseJsonToObject(String jsonString) {
Gson gson = new Gson();
AgentStrategy agent = gson.fromJson(jsonString, AgentStrategy.class);
// PATTERNS
Map patternsMap = (Map) map.get("Patterns");
Map sellMap = (Map) patternsMap.get("Sell");
Map buyMap = (Map) patternsMap.get("Buy");
agent.buyPatternsUsed = new ArrayList<>(sellMap.values());
agent.buyPatternsUsed = new ArrayList<>(buyMap.values());
return agent;
}
But I get an error on this line at the pattern parse part:
agent.buyPatternsUsed = new ArrayList<>(sellMap.values());
With: Exception in thread "main" java.lang.ClassCastException: class java.util.ArrayList cannot be cast to class java.util.Map (java.util.ArrayList and java.util.Map are in module java.base of loader 'bootstrap')
How can I parse all the patterns from buy and sell to a String Array (seperate)?
How can I parse all the patterns from buy and sell to a String Array (seperate)?
The JSON you posted has two arrays and you're trying to parse them as maps. Parse them as arrays (lists).
List sellList = (List) patternsMap.get("Sell");
List buyList = (List) patternsMap.get("Buy");
That said, the true power of GSON (and JSON parsers in general) is that do the heavy work for you if you model your classes correctly. You could have a "Patterns" class that has two lists of strings, then the strategy class would have a "Pattern". For example:
class Patterns {
List<String> Buy;
List<String> Sell;
}
class Agent Strategy {
Patterns Patterns;
}
Now, when you parse the object, because the class structure matches the json structure, the lists are parsed automatically for you:
AgentStrategy agent = gson.fromJson(jsonString, AgentStrategy.class);
// agent.Patterns.Buy and .Sell now have the lists
Then you could just define helpers to get the data you care about:
class Agent Strategy {
Patterns Patterns;
public getBuyPatternsUsed() { return Patterns.Buy; }
public getSellPatternsUsed() { return Patterns.Sell; }
}
P.S. - Tip: when you see "class cast exception" use your debugger to step through up to line where the crash happens and see what type you're actually getting compared to what you expect. That will help you debug your issue.
"Buy":[
"buy_pattern_1",
"buy_pattern_2"
],
"Sell":[
"sell_pattern_1",
"sell_pattern_2"
]
The Buy and Sell are arrays.
So the following cast will throw exception
Map sellMap = (Map) patternsMap.get("Sell");
Map buyMap = (Map) patternsMap.get("Buy");
Suggestion
Try to use annotations to map the java attribute name and json field name
i have only named few fields (using #SerializedName annotation)
static class PriceDropSell {
#SerializedName("Buy")
List<String> buy;
#SerializedName("Sell")
List<String> sell;
}
static class AgentStrategy {
private String Market;
private String Coin;
private double EmergencyPerc;
private double TakeProfitPerc;
private String ProtectiveOrdersEnabled;
public double EMACrossMarginPerc;
public String EMABuySellPeriod;
public String EMABuySellNameLow;
public String EMABuySellNameHigh;
public String EMAUnfreezePeriod;
public String EMAUnfreezeNameLow;
public String EMAUnfreezeNameHigh;
private String SimTemplate;
#SerializedName(("Patterns"))
private PriceDropSell Patterns;
}
public static void main(String[] args) {
Gson gson = new Gson();
AgentStrategy agentStrategy = gson.fromJson(str, AgentStrategy.class);
System.out.println(gson.toJson(agentStrategy));
}

How to serialize an object to a list of one elements with gson

I have some json string like this:
example1
{
"path":{
"start":"abc"
},
"name":"Fork1"
}
example2
{
"path":[{
"start":"abc"
},
{
"start":"def"
}],
"name":"Fork1"
}
and I want to serialize with one JAVA object like this:
#Data
public static class ForkNode {
private List<Path> path;
private String name;
}
#Data
public static class Path {
private String start;
}
new Gson().fromJson(jsonStr, ForkNode.class)
but it will throw an exception
IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 2 column 11 path $.path
So how do I treat the first example as a list of one elements?
Or is there any way I can serialize two different types of json strings with one object?
I don't think it is a good way to serialize two different types of json strings with ONE object.
For example 1, the Object should be like this:
#Data
public static class ForkNode {
// only one path
private Path path;
private String name;
}
#Data
public static class Path {
private String start;
}
new Gson().fromJson(jsonStr, ForkNode.class)
While For example 2, the Object should be like this:
#Data
public static class ForkNode {
// several paths
private List<Path> path;
private String name;
}
#Data
public static class Path {
private String start;
}
new Gson().fromJson(jsonStr, ForkNode.class)
In JSON:
Objects are enclosed directly in curly brackets {} While JSON
Arrays that are enclosed in square brackets [] inside JSON Objects.
One more thing, If you do really want to do that, I think you need to implement a custom deserializer by yourself. Please ref the doc of Gson.
I solved it by modify JsonObject.
I use this code to convent JsonObject to JsonArray, so I can deserializer it like JsonArray.
public void objectToArray(JsonObject jsonObject, String node) {
JsonElement jsonElement = jsonObject.get(node);
if (jsonElement instanceof JsonObject) {
JsonArray array = new JsonArray();
array.add(jsonElement);
jsonObject.remove(node);
jsonObject.add(node, array);
}
}

What's the best way to handle JSON API responses using GSON?

I'm working on a project that communicates with an API using JSON. This is my first attempt at JSON and I've been away from java for a few/several years, so please bear with me.
Here is an idea of what the data looks like:
String 1:
[{
"apicall1":
[{
"thisField":"thisFieldData",
"thatField":"thatFieldData",
"anotherField":"anotherFieldData"
}]
}]
String 2:
[{
"apicall2":
[{
"thatField":"thatFieldData",
"someFieldsAreTheSame":"someFieldsAreTheSameData",
"otherFieldsAreNotTheSame":"otherFieldsAreNotTheSame"
}]
}]
As you can see from my data example, the API returns a JSON string that contains the api used. The array inside contains the data. The API's have a lot of data fields in common but they are unrelated beyond that.
EDIT: There are dozens of these API's types that will need to be handled.
What I am trying to do is create a response class that accepts all of the JSON strings and returns an object containing the appropriate data.
For Example:
Gson gson = new Gson(); //Custom TypeAdapter goes here if needed.
Response apicall2 = gson.fromJson(apicall2String, Response.class);
System.out.println(apicall2.thatField); //Prints thatFieldData
System.out.println(apicall2.someFieldsAreTheSame); //Prints someFieldsAreTheSameData
System.out.println(apicall2.otherFieldsAreNotTheSame); //Prints otherFieldsAreNotTheSameData
This is where I am lost. Here is what I have so far. I think I need to use a TypeAdapter here but haven't been able to figure how to apply that to my case.
public class Response { //Change to TypeAdapter possibly?
}
public class apicall1 {
String thisField;
String thatField;
String anotherField;
}
public class apicall2 {
String thatField;
String someFieldsAreTheSame;
String otherFieldsAreNotTheSame;
}
You can use Gson's TypeToken class to deserialize json into object. Below is an example:
JSON:
[{ "apicall1":
[{
"thisField":"thisFieldData",
"thatField":"thatFieldData",
"anotherField":"anotherFieldData"
}]
}]
Model:
class Response{
private List<Result> apicall1;
class Result{
private String thisField;
private String thatField;
private String anotherField;
public String getThisField() {
return thisField;
}
public void setThisField(String thisField) {
this.thisField = thisField;
}
public String getThatField() {
return thatField;
}
public void setThatField(String thatField) {
this.thatField = thatField;
}
public String getAnotherField() {
return anotherField;
}
public void setAnotherField(String anotherField) {
this.anotherField = anotherField;
}
}
public List<Result> getApicall1() {
return apicall1;
}
public void setApicall1(List<Result> apicall1) {
this.apicall1 = apicall1;
}
}
Converter:
public static void main(String[] args) {
String response = "[{ \"apicall1\": [{ \"thisField\":\"thisFieldData\", \"thatField\":\"thatFieldData\", \"anotherField\":\"anotherFieldData\" }]}]";
Gson gson = new Gson();
List<Response> responses = gson.fromJson(response, new TypeToken<List<Response>>(){}.getType());
System.out.println(responses.get(0).getApicall1().get(0).getThisField());
}
I don't know if you want both adapters in one class. Might not be the best OOP design.
To achieve it you would need to do something like so:
public class DoublyTypeAdapter implements JsonDeserializer<ApiCallTypeParent>
{
Gson gson = new Gson();
#Override
public ApiCallTypeParent deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext)
throws JsonParseException {
JsonObject json = jsonElement.getAsJsonObject();
ApiCallTypeParent desrializeIntoMe;
// Detect which type to implement
if(apiTypeOne(type) {
desrializeIntoMe = new TypeOne();
} else {
desrializeIntoMe = new TypeTwo();
}
for (Map.Entry<String, JsonElement> entry : json.entrySet())
{
switch(entry.getKey()){
case "thisField":
desrializeIntoMe.setThisField(entry.getValue().getAsString());
break;
......
default: // We don't care
break;
}
}
return desrializeIntoMe ;
}
}

How to parse json data using in java

I am getting this data from server how to parse this data in java .
LabelField jsonResult = new LabelField(connectJson.response);
"[{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"},{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"},{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"},{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"},{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"}]"
I am getting response in jsonResult variable
You can use libraries like Jackson to do the same. There is also Google's GSON which will help you do the same. See this example
Take a look at the JSONParser Object in this Tutorial
If you are using Eclipse plugin than may JSON library included in you SDK.
Use below code to parse your JSON string got from the server.
String test = "[{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"},{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"},{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"},{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"},{\"screen_refresh_interval\":4,\"station_list_last_update\":\"update4\"}]";
JSONArray array = new JSONArray(test);
JSONObject obj = (JSONObject) array.get(0);
Your String look like you got JSON Array from the server.
First convert your Json string to JSON Array by
JSONArray array = new JSONArray(Your JSON String);
Each element in array represent JSON Object.You can read JSON Object by
JSONObject obj = (JSONObject) array.get(Index);
You can read parameter from Object to any String variable by :
String valueStr = obj.getString("screen_refresh_interval");
May this help you.
Design a class (viz CustomClass) first with screen_refresh_interval and station_list_last_update as properties. And Make a collection class for CustomClass
I'm using Gson as deserializer. Other libraries are also available.
public class Container {
private CustomClass[] classes;
public CustomClass[] getClasses() {
return classes;
}
public void setClasses(CustomClass[] classes) {
this.classes = classes;
}
}
public class CustomClass {
private String screen_refresh_interval;
private String station_list_last_update;
public String getScreen_refresh_interval() {
return screen_refresh_interval;
}
public void setScreen_refresh_interval(String screen_refresh_interval) {
this.screen_refresh_interval = screen_refresh_interval;
}
public String getStation_list_last_update() {
return station_list_last_update;
}
public void setStation_list_last_update(String station_list_last_update) {
this.station_list_last_update = station_list_last_update;
}
}
Gson gson = new Gson();
Container customClassCollection = gson.fromJson(jsonResult, Container.class);

JSON array in GSON parses, but objects are empty

i am attempting to turn a json string into objects with gson.
I have a very simple example below, and it runs, but the resulting answer is empty, ie: my Answer objects's text field is empty.
import com.google.gson.*;
public class Meow {
public static void main(String[] args) throws Exception{
Gson gson = new Gson();
String jsonOutput = "[{\"answer\":{\"text\":\"text1\"}},{\"answer\":{\"text\":\"text2\"}} ]";
Answer[] a = gson.fromJson(jsonOutput, Answer[].class);
for(Answer i:a) {
System.out.println(i.text);
}
}
public class Answer {
public String text;
public Answer(String text) {
super();
this.text=text;
}
public String toString(){
return text;
}
public void setText(String a){
this.text=a;
}
}
}
Because your JSON doesn't match your class.
Your JSON right now is an array of objects, each containing an answer object as a field.
Your JSON the way you have things would need to look like:
String jsonOutput = "[{\"text\":\"text1\"},{\"text\":\"text2\"}]";
Edit to add from comments:
If you can't change the output, you need a "wrapper". Something like:
public class AnswerWrapper {
public Answer answer;
// etc
}
And use an array of those. That is what the JSON will map to. It can't see them as Answer objects because ... they're not.
One More Edit to Add: Your other option is to write custom deserializers for your classes. I'm a bit mixed on whether you should do this or not, but it will work. The reason I say that is that you have JSON that isn't an array of Answer objects, but you want it to be. I think I'd be annoyed if I came across this in production code because without understanding what was going on it could be confusing.
With that caveat being said, you can create a custom JsonDeserializer and use GsonBuilder:
class AnswerDeserializer implements JsonDeserializer<Answer> {
public Answer deserialize(JsonElement je, Type type,
JsonDeserializationContext jdc)
throws JsonParseException {
return new Answer(je.getAsJsonObject().get("answer")
.getAsJsonObject().get("text").getAsString());
}
}
Then your code would look like:
public static void main(String[] args) throws Exception{
String jsonOutput = "[{\"answer\":{\"text\":\"text1\"}},{\"answer\":{\"text\":\"text2\"}} ]";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Answer.class, new AnswerDeserializer());
Gson gson = gsonBuilder.create();
Answer[] a = gson.fromJson(jsonOutput, Answer[].class);
for(Answer i:a) {
System.out.println(i.text);
}
}
If it were me, and I had JSON that wasn't what I needed it to be but wanted to use GSON to directly serialize/deserialize I'd create the Answer class as a wrapper that hid the details:
/**
* Due to how our JSON is being provided we created an inner
* class.
**/
public class Answer {
private RealAnswer answer;
private class RealAnswer {
public String text;
}
...
}
With the public getters/setters for Answer accessing the private RealAnswer. It just seems way cleaner and easier to understand for the next guy.

Categories