I am trying to parse Json object which is;
{
"results":[
{
"face":{
"id":361122.0,
"photo_hash":"0a2aaff34fd576fc1caf711d88cbfd53",
"x1":699,
"x2":1020,
"y1":271,
"photo":" ",
"thumbnail":" ",
"meta":"",
"timestamp":"2016-07-28T08:50:43.710183",
"y2":592
},
"confidence":0.93187
},
{
"face":{
"id":361260.0,
"photo_hash":"767bf4df0c8a04361aaf5e6b74eb4d8c",
"x1":-25,
"x2":147,
"y1":10,
"photo":" ",
"thumbnail":" ",
"meta":"",
"timestamp":"2016-07-28T15:13:09.086390",
"y2":165
},
"confidence":0.926754
}
]
}
And I am using such code for parsing confidence and thumbnail :
resultParams[i].confidence = jsonObject.getJSONArray("results").getJSONObject(i).getString("confidence");
resultParams[i].thumbnail = jsonObject.getJSONArray("results").getJSONObject(i).getJSONObject("face").getString("thumbnail");
However it gives exception "java.lang.NullPointerException: Attempt to write to field on a null object reference"
Could you please help me how to successfully parse it?
To give this an answer:
"java.lang.NullPointerException: Attempt to write to field on a null object reference"
Means your left side is the problem. resultParams[i] is most probably null.
If you know what kind of json-object will you receive(or maybe you have an API), you can make an object of this class by for example Jackson library. And then get access to "face" object with its getter.
yourObject.getResults().get(i).getFace().getThumbnail();
Firstly based on the JSON response you create your model object.
You can make use of GSON for converting the whole content into object.
This can be acheived using other libaries too.
So here are the Model objects for your JSON
import java.util.Date;
import java.util.List;
class Result {
private List<PersonDetails> results;
// generate setter and getter
}
class PersonDetails
{
private ImageDetail face;
private Float confidence;
// generate setter and getter
}
class ImageDetail
{
private Long id;
private String photo_hash;
private Integer x1,x2,y1,y2;
private String thumbnail;
private String meta;
private String photo;
private Date timestamp;
// generate setter and getter
}
Now use GSON to convert your JSON.
public class JsonTransaformer1 {
#SuppressWarnings("unchecked")
public static void main(String[] args) {
String text = "Place your JSON Response as input that you posted";
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new GsonUTCdateAdapter()).create();
Result obj = gson.fromJson(text, Result.class);
System.out.println(obj.getResults().size());
System.out.println(obj.getResults().get(0).getFace().getId());
System.out.println(obj.getResults().get(0).getConfidence());
}
}
As the Date format that is present in your JSON response is different we need to register the Adapter to parse the date.
Look into this link for parsing
Java Date to UTC using gson
class GsonUTCdateAdapter implements JsonSerializer<Date>,JsonDeserializer<Date> {
private final DateFormat dateFormat;
public GsonUTCdateAdapter() {
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US); //This is the format I need
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); //This is the key line which converts the date to UTC which cannot be accessed with the default serializer
}
#Override public synchronized JsonElement serialize(Date date,Type type,JsonSerializationContext jsonSerializationContext) {
return new JsonPrimitive(dateFormat.format(date));
}
#Override public synchronized Date deserialize(JsonElement jsonElement,Type type,JsonDeserializationContext jsonDeserializationContext) {
try {
return dateFormat.parse(jsonElement.getAsString());
} catch (ParseException e) {
throw new JsonParseException(e);
}
}
}
Now running the main you will get the Object representation of JSON.
Related
I have JSON response which looks like that:
{
"response":[
"Some number (for example 8091)",
{
"Bunch of primitives inside the first JSONObject"
},
{
"Bunch of primitives inside the second JSONObject"
},
{
"Bunch of primitives inside the third JSONObject"
},
... (and so on)
]
}
So it's an array with first integer element and other elements are JSONObject.
I don't need integer element to be parsed. So how do I handle it using GSON?
I would solve this problem by creating a custom JsonDeserializer and registering it to your Gson instance before parsing. This custom deserializer would be set up to handle both ints and real objects.
First you need to build up a series of model objects to represent the data. Here's a template for what that might look like:
private static class TopLevel {
#SerializedName("response")
private final List<ResponseElement> elements;
private TopLevel() {
this.elements = null;
}
}
private static class ResponseInteger implements ResponseElement {
private final int value;
public ResponseInteger(int value) {
this.value = value;
}
}
private static class ResponseObject implements ResponseElement {
#SerializedName("id")
private final String id;
#SerializedName("text")
private final String text;
private ResponseObject() {
this.id = null;
this.text = null;
}
}
private interface ResponseElement {
// marker interface
}
TopLevel and ResponseObject have private constructors because they are going to let Gson set their fields using reflection, while ResponseInteger has a public constructor because we're going to manually invoke it from our custom deserializer.
Obviously you will have to fill out ResponseObject with the rest of its fields.
The deserializer is relatively simple. The json you posted contains only two kinds of elements, and we'll leverage this. Each time the deserializer is invoked, it checks whether the element is a primitive, and returns a ResponseInteger if so (or a ResponseObject if not).
private static class ResponseElementDeserializer implements JsonDeserializer<ResponseElement> {
#Override
public ResponseElement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive()) {
return new ResponseInteger(json.getAsInt());
}
else {
return context.deserialize(json, ResponseObject.class);
}
}
}
To use this deserializer, you'll have to register it with Gson using the GsonBuilder object.
private static Gson getGson() {
return new GsonBuilder()
.registerTypeAdapter(ResponseElement.class, new ResponseElementDeserializer())
.create();
}
And that's it. Now you can use this Gson object to easily parse TopLevel objects!
public void parseJson() {
TopLevel t = getGson().fromJson(json, TopLevel.class);
for (ResponseElement element : t.elements) {
System.out.println(element);
}
}
8061
[450602: Поздравляем!]
[451700: С реакцией чата и рассуждениями Папани после рипа..]
[451578: Помним...Любим...Скорбим...<br>2107 забирает лучших]
[451371: Земля тебе пухом братишка]
[451332: Доигрался, минус 900 экзов<br><br>R I P]
[451269: ]
[451242: https://www.twitch.tv/arthas подрубка<br><br>evilpapech.ru - скидка 30% на футболки!]
[451217: ]
[451181: или так це жерстко?]
[451108: ]
I used these toString() methods, which I omitted above for brevity:
#Override
public String toString() {
return Integer.toString(value);
}
#Override
public String toString() {
return "[" + id + ": " + text + "]";
}
Try this
Gson gson = new Gson();
// Reading from a file.
Example example = gson.fromJson(new FileReader("D:\\content.json"), Example.class);
POJO
package com.example;
public class Example {
private List<Integer> response = null;
public List<Integer> getResponse() {
return response;
}
public void setResponse(List<Integer> response) {
this.response = response;
}
}
Basically this structure is the wrong format for JSON data.
You need to remove the number, or put this number as a field in the same object like the one below (call ObjectA) and consider this is an array of ObjectA.
Then everything should work well. Try the code below:
public class Response {
#SerializedName("response")
#Expose
public List<ObjectA> objectA = null;
}
public class ObjectA {
#SerializedName("value")
#Expose
public Integer value;
#SerializedName("description")
#Expose
public String description;
}
Response response = new Gson().fromJson(responseString, Response.class);
Please use below ValueObject format which doesn't parse first integer element
public class ResponseVO {
public List<Response> response = new ArrayList();
public class Response {
public final long id;
public final long from_id;
...
}
}
I have a list of object that I want update.
Basically I have created my object using spring but the content of the object is empty.
I want to update the List of objects from a json file using Jackson parser.
The json file is compatible with the object. that means that I am letting the mapper to auto-detect the setters.
What happening is that the mapper is loading the object to the list as
As LinkedHashMap object and not as My object
This is my json
[
{
"startDate":"01/06/2014 08:00",
"endDate":"01/06/2014 16:00",
"shiftType":"Regular",
"capacity":5
},
{
"startDate":"01/06/2014 16:00",
"endDate":"01/06/2014 23:00",
"shiftType":"Regular",
"capacity":5
},
{
"startDate":"01/06/2014 23:00",
"endDate":"02/06/2014 08:00",
"shiftType":"Regular",
"capacity":5
},
{
"startDate":"02/06/2014 08:00",
"endDate":"02/06/2014 16:00",
"shiftType":"Regular",
"capacity":5
},
]
this is my object
package il.co.shiftsgenerator.engine.model;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class ShiftConfiguration {
private int capacity;
private String shiftType;
private String startDate;
private String endDate;
private SimpleDateFormat dateFormat;
public int getCapacity() {
return capacity;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) throws ParseException {
dateFormat.parse(startDate);
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) throws ParseException {
dateFormat.parse(endDate);
this.endDate = endDate;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
public String getShiftType() {
return shiftType;
}
public void setShiftType(String shiftType) {
this.shiftType = shiftType;
}
public SimpleDateFormat getDateFormat() {
return dateFormat;
}
public void setDateFormat(SimpleDateFormat dateFormat) {
this.dateFormat = dateFormat;
}
#Override
public String toString() {
return "ShiftConfiguration [capacity=" + capacity + ", shiftType="
+ shiftType + ", startDate=" + startDate + ", endDate="
+ endDate + "]";
}
}
this is how I am trying to load the data
ObjectMapper mapper = new ObjectMapper();
InputStream stream = fileLoaderHelper.getFileAsStream(SHIFT_CONFIG_LIST_JSON_FILE);
List<ShiftConfiguration> shiftBeans = new ArrayList<ShiftConfiguration>();
for (int i = 0; i < 21; i++) {
ShiftConfiguration shiftBean = context.getBean(ShiftConfiguration.class);
shiftBeans.add(shiftBean);
}
ObjectReader readerForUpdating = mapper.readerForUpdating(shiftBeans);
readerForUpdating.readValues(stream);
System.out.println(shiftBeans);
It may not be detecting the correct object due to your date format. I would try explicitly telling Jackson the format for your datetimes and maybe that will straighten things out. Try something like
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm");
mapper.setDateFormat(df);
Before your mapper.readerForUpdating call and see if that does it.
This is because you are not specifying actual type to use: you are reading List of ShiftConfiguration, but you are not specifying type. Jackson has no idea what the expected type is: you are just handing it an object to update, and due to Java Type Erasure, Lists do not have runtime generic type information.
So you'd need to create readerFor(new TypeRefererence<List<ShiftConfiguration>>() { }) and then the method to indicate you want to update List.
Alternatively you might just want to read the new list, giving type information needed, and concatenate manually with addAll(...).
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 ;
}
}
I have java class like:
public class Sample{
int foo=5;
int bar=6;
}
now I want to generate JSON object but without bar field:
{"foo":5}
What is a best way to accomplish that?
Should I compose JSON string manually, or can I use some library, or generator?
Should I compose JSON string manually
Avoid this, it's all to easy to make invalid json this way. Use of a library ensures proper escaping of characters that would otherwise break the output.
Gson ignores transient fields:
public class Sample {
private int foo = 5;
private int transient bar = 6;
}
Gson gson = new Gson();
Or you can choose which to include with Expose attribute:
public class Sample {
#Expose private int foo = 5;
private int bar = 6;
}
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Then whichever approach, do this:
String json = gson.toJson(obj);
To get your desired {"foo":5}
You can use the Jackson to solve your problem. Follow the below step -
Step 1 - Make a method which will convert Java object to Json
public class JsonUtils {
public static String javaToJson(Object o) {
String jsonString = null;
try {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.UNWRAP_ROOT_VALUE,true);
jsonString = objectMapper.writeValueAsString(o);
} catch (JsonGenerationException e) {
logger.error(e);
} catch (JsonMappingException e) {
logger.error(e);
} catch (IOException e) {
logger.error(e);
}
return jsonString;
}
}
Step 2 Model Class
package com.javamad.model;
import org.codehaus.jackson.annotate.JsonIgnore;
public class Sample{
int foo=5;
public int getFoo() {
return foo;
}
public void setFoo(int foo) {
this.foo = foo;
}
#JsonIgnore
public int getBar() {
return bar;
}
public void setBar(int bar) {
this.bar = bar;
}
int bar=6;
}
Step 3 Convert your java class to json
Sample sample = new Sample()
JsonUtils.javaToJson(sample);
you can try Gson, JSON library, to convert object to/from json.
these two methods are helpfull:
toJson() – Convert Java object to JSON format
fromJson() – Convert JSON into Java object
Gson gson = new Gson();
// convert java object to JSON format,
// and returned as JSON formatted string
String json = gson.toJson(obj);
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)