Java Jackson: Deserialize JSON with dynamic Names into JavaClass - java

I'm trying to deserialize JSON using jackson. The problem is that field names always change.
Here is an example JSON:
{
2021-08-02: [
{
label: "OnlineGallery",
nb_uniq_visitors: 1,
nb_visits: 2,
nb_events: 2,
nb_events_with_value: 0,
sum_event_value: 0,
min_event_value: 0,
max_event_value: 0,
avg_event_value: 0,
segment: "eventCategory==OnlineGallery",
idsubdatatable: 1
}
],
2021-08-03: [ ],
2021-08-04: [ ]
}
I´m getting the data by Resttemplate and try to deserialize into Java Class but it doesn't work:
private EventsGetCategory getEventFromAPI(Date startdate, Date enddate) {
RestTemplate restTemplate = new RestTemplate();
DateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd");
ResponseEntity<EventsGetCategory> response =
restTemplate.getForEntity(
matomoUrl + "index.php?module=API&label=OnlineGallery&method=Events.getCategory&secondaryDimension=eventAction&idSite=1&period=day&date=" + dateFormat.format(startdate) + "," + dateFormat.format(enddate) + "&format=JSON&filter_limit=-1"
+ "&token_auth=" + tokenAuth,
EventsGetCategory.class);
return response.getBody();
}
EventsGetCategory Class:
#Data
public class EventsGetCategory {
#JsonAnySetter
private Map<String, List<EventDetails>> details;
}
EventDetails Class:
#Data
public class EventDetails {
String label;
int nb_uniq_visitors;
int nb_visits;
int nb_events;
int nb_events_with_value;
int sum_event_value;
int min_event_value;
int max_event_value;
int avg_event_value;
String segment;
int idsubdatatable;
}
Can someone help me please?

Update Your EventsGetCategory class like this
public class EventsGetCategory {
private Map<String, List<EventDetails>> details;
#JsonAnySetter
public void setDetails(String key, List<EventDetails> val) {
if (this.details == null) {
this.details = new HashMap<>();
}
this.details.put(key, val);
}
}

if the field names are always changed then you can not use a class like EventDetails to map the JSON object to a java class, instead of EventDetails class, you have to use Map<String, Object> where you can store dynamic key values.

Related

Java - Extract array String from JSON and convert to JSON format

I have a JSON String as below:
"{ \"password\":\"des123\",\"ROU_DATA\":[{\"FORM_RECEIVING_TIME\":\"12:00:00\",\"REMARKS\":\"Redemption of Unit\"}, {\"FORM_RECEIVING_TIME\":\"13:00:00\",\"REMARKS\":\"sALE of Unit\"}] }";
Now I want to extract the Array from it and need to use it as a separate pojo class so that I can iterate over each value..
Now the problem is, when I try to convert the complete String to Map and get the Array value from the map.. It transforms its format to MAp format like:
{FORM_RECEIVING_DATE = 12:00:00, etc..}
However json string should be {"FORM_RECEIVING_DATE": "12:00:00", etc..}
due to the MAp format its now allowing me to parse it using my POJO Class..
Please help to convert it to my JSONFormat ...
**NOTE: Please note that I can only use Jackson **.
CLASS A
ObjectMapper mapper2 = new ObjectMapper();
Map<String, Object> map;
map = mapper2.readValue(json, new TypeReference<Map<String, Object>>(){});
System.out.println("map: " + map.get("ROU_DATA") );
String array = map.get("ROU_DATA").toString();
String json2 = new ObjectMapper().writeValueAsString(array.replace("[", "").replace("]", ""));
String json3 = new ObjectMapper().writeValueAsString(json2);
System.out.println("json2>>" + json2);
System.out.println("json2>>" + json3);
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 1. convert JSON array to Array objects
ROU[] pp1 = mapper.readValue("{" + array.replace("=", ":") + "}", ROU[].class);
for (ROU person : pp1) {
System.out.println(person.getRemarks());
}
CLASS B
import com.fasterxml.jackson.annotation.JsonProperty;
public class ROU {
#JsonProperty("FORM_RECEIVING_TIME")
private String formdate;
#JsonProperty("REMARKS")
private String remarks;
public String getFormdate() {
return formdate;
}
public void setFormdate(String formdate) {
this.formdate = formdate;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
}
map.get("ROU_DATA") returns a List object, and the toString() method of List does not generate JSON text.
You don't need to convert back to a JSON text just to get the ROU[] created, just call convertValue(...).
String input = "{ \"password\":\"des123\",\"ROU_DATA\":[{\"FORM_RECEIVING_TIME\":\"12:00:00\",\"REMARKS\":\"Redemption of Unit\"}, {\"FORM_RECEIVING_TIME\":\"13:00:00\",\"REMARKS\":\"sALE of Unit\"}] }";
ObjectMapper mapper2 = new ObjectMapper();
Map<?, ?> json = mapper2.readValue(input, Map.class);
ROU[] pp1 = mapper2.convertValue(json.get("ROU_DATA"), ROU[].class);
for (ROU person : pp1)
System.out.println(person.getRemarks());
Output
Redemption of Unit
sALE of Unit
class A
public class ROU {
#JsonProperty("FORM_RECEIVING_TIME")
private String formdate;
#JsonProperty("REMARKS")
private String remarks;
public String getFormdate() {
return formdate;
}
public void setFormdate(String formdate) {
this.formdate = formdate;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
}
class B
public class ObjOuter {
private String password;
#JsonProperty("ROU_DATA")
private List<ROU> rous;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<ROU> getRous() {
return rous;
}
public void setRous(List<ROU> rous) {
this.rous = rous;
}
}
json to Object
ObjectMapper mapper = new ObjectMapper();
try {
ObjOuter outer = mapper.readValue(str, ObjOuter.class);
for (ROU rou : outer.getRous()) {
System.out.println(rou.getFormdate());
System.out.println(rou.getRemarks());
}
} catch (IOException e) {
e.printStackTrace();
}

How to convert csv to nested beans using OpenCSV or any other library?

I'm making an HTTP call to get an CSV file and I'm using OpenCSV to convert string equivalent of CSV file to plain old java object. I have skipped the logic to make http call to fetch csv since it had sensitive information. The converted Student object from the below code has null values for "collegeTiming" property. How to map this value from CSV ? Can someone please suggest? Thanks in advance!
PFB my dependency in pom.xml
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.0</version>
</dependency>
My Input CSV
"id", "name", "monday_open_time", "monday_close_time", "tuesday_open_time", "tuesday_close_time", "wednesday_open_time", "wednesday_close_time", "thursday_open_time", "thrusday_close_time", "friday_open_time", "friday_close_time"
1, ABCD, 07.00.00,21.00.00, 08.00.00,22.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00
2, ABCD, 08.00.00,21.00.00, 07.00.00,14.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00
3, ABCD, 07.00.00,21.00.00, 10.00.00,13.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00
4, ABCD, 09.00.00,21.00.00, 11.00.00,20.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00
I want to convert the input csv to below Student bean
{
"id" : 1,
"name": ABC,
"collegeTime" : {
"monday":[ 07.00.00, 21.00.00 ],
"tuesday":[ 08.00.00, 22.00.00 ],
"wednesday":[ 07.00.00, 21.00.00 ],
"thrusday":[ 07.00.00, 21.00.00 ],
"friday":[ 07.00.00, 21.00.00 ],
}
}
Student.java
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.opencsv.bean.CsvBindByName;
public class Student {
#CsvBindByName
#JsonProperty("id")
private String id;
#JsonProperty("name")
#CsvBindByName
private String name;
#JsonProperty("collegeTiming")
private List<CollegeTiming> collegeTimings;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<CollegeTiming> getCollegeTimings() {
return collegeTimings;
}
public void setCollegeTimings(List<CollegeTiming> collegeTimings) {
this.collegeTimings = collegeTimings;
}
}
CollegeTiming.java
import com.fasterxml.jackson.annotation.JsonProperty;
public class CollegeTiming {
#JsonProperty("collegeTime")
private CollegeTime collegeTime;
public CollegeTime getCollegeTime() {
return collegeTime;
}
public void setCollegeTime(CollegeTime collegeTime) {
this.collegeTime = collegeTime;
}
}
CollegeTime.java
public class CollegeTime {
private String day;
private String startTime;
private String endTime;
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}
//Converting csv to Student object using OpenCSV.
Note: csvAsString is string representation of csv file (I made a HTTP call to fetch this information.
HeaderColumnNameMappingStrategy<Student> strategy = new HeaderColumnNameMappingStrategy<>();
strategy.setType(Student.class);
CsvToBean<Student> csvToBean = new CsvToBeanBuilder<Student>(new StringReader(csvAsString))
.withType(Student.class)
.withMappingStrategy(strategy)
.withIgnoreLeadingWhiteSpace(true)
.build();
List<Student> = = csvToBean.parse();
When I print the Student object, null is getting printed for "collegeTiming" property of Student object. How to map the csv file to nested object (CollegeTime) ?
This seems a bit odd, you are trying to push flat data into a hierarchy. You will need to do some custom processing there since your keys also do not match the model you are trying to build. I have made an example on how to achieve that using the CSVReader and Jackson's ObjectMapper:
public class CSVMappingTest {
static String csv = "\"id\", \"name\", \"monday_open_time\", \"monday_close_time\", \"tuesday_open_time\", \"tuesday_close_time\", \"wednesday_open_time\", \"wednesday_close_time\", \"thursday_open_time\", \"thrusday_close_time\", \"friday_open_time\", \"friday_close_time\"\n" +
"1, ABCD, 07.00.00,21.00.00, 08.00.00,22.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00\n" +
"2, ABCD, 08.00.00,21.00.00, 07.00.00,14.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00\n" +
"3, ABCD, 07.00.00,21.00.00, 10.00.00,13.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00\n" +
"4, ABCD, 09.00.00,21.00.00, 11.00.00,20.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00, 07.00.00,21.00.00";
public static void main(String[] args) throws IOException {
CSVReader reader = new CSVReader(new StringReader(csv));
ObjectMapper mapper = new ObjectMapper();
String[] keys = reader.readNext(); // headers
String[] values = reader.readNext();
while(values != null) {
Student convertValue = mapper.convertValue(csvToMap(keys, values), Student.class);
System.err.println(mapper.writeValueAsString(convertValue));
values = reader.readNext();
}
}
public static Map<String, String> csvToMap(final String[] headers, final String[] vals) {
if(headers == null || vals == null) {
throw new NullPointerException("Empty input for csv to map");
}
if(headers.length != vals.length) {
throw new IllegalArgumentException("Header and value count do not match for csv to map");
}
Map<String, String> res = new HashMap<>();
IntStream.range(0, vals.length).forEach( i -> res.put(headers[i], vals[i]));
return res;
}
public static class Student {
#JsonProperty("id")
String id;
#JsonProperty("name")
String name;
#JsonProperty
Map<String, String> studentTimings = new HashMap<>();
#JsonAnySetter
public void setTime(String key, String value) {
studentTimings.put(key, value);
}
}
}
Explanations:
I only use the CSVReader to retrieve a row.
I then use a csvToMap to create a mapping of header-value.
I then use the convertion method on jackson to auto-create the bean i want.
The important bit is here:
#JsonAnySetter
public void setTime(String key, String value) {
studentTimings.put(key, value);
}
This tells jackson that any property not directly wrapped will be send here.
This is where you would process your times and manually group them into whatever buckets you want. I do not see any other alternative since your flat input does not match the properties you are trying to create.
Neither OpenCSV nor Jackson are processors. They are not responsible for transforming your data, their purpose is as simple as "find the key and call the setter". You can use custom serialiser of any form in order to tell it how to create the objects you want, but the default is as simple as the statement above.
I am sure there is an OpenCSV method for this as well, however I don't know it :)
I hope that helps,
Artur
P.s. i did not copy your entire model but rather just pushed the values into a map. The output of my parsing would then be for example:
{
"id": "3",
"name": " ABCD",
"studentTimings": {
"friday_close_time": "21.00.00",
"friday_open_time": " 07.00.00",
"monday_close_time": "21.00.00",
"monday_open_time": " 07.00.00",
"thrusday_close_time": "21.00.00",
"thursday_open_time": " 07.00.00",
"tuesday_close_time": "13.00.00",
"tuesday_open_time": " 10.00.00",
"wednesday_close_time": "21.00.00",
"wednesday_open_time": " 07.00.00"
}
}
BufferedReader br = null;
List<Student> objLst = new ArrayList<Student>();
InputStreamReader inStreamReader = null;
inStreamReader = new
InputStreamReader(ReadAccountsUtil.class.getClassLoader().getResourceAsStream("someFile.csv"));
CsvReader csvReader = new CsvReader(inStreamReader);
String objStr[] = {};
JavaPojoClass id = new Id();
try {
while (csvReader.readRecord()) {
objStr = csvReader.getRawRecord().split(",");
student = new Student();
student.setRollNo(new Short(objStr[0]));
student.setName(new String(objStr[1]));
student.setAdd(new String(objStr[2]));
student.setEmail(new String(objStr[3]));
objLst.add(student);
}
} catch (Exception ex) {
if(inStreamReader != null){
try {
inStreamReader.close();
} catch (IOException e) {
LOGGER.error("Error in closing the input streams"+ e.getMessage());
}
}
LOGGER.error("Error in reading the Student file"+ ex.getMessage());
}
return objLst;
}
public static void main(String[] args) throws IOException{
String fileName = "c:\\test.csv";
char separator = ';';
List<TestDTO> obj= new CsvToBeanBuilder(new
FileReader(fileName)).withSeparator(separator)
.withType(TestDTO.class)
.build()
.parse();
obj.forEach(System.out::println);
}
import com.opencsv.bean.CsvBindByName;
import lombok.*;
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
public class TestDTO {
#CsvBindByName(column = "EXTERNAL_ID")
private String externalId;
#CsvBindByName(column = "ID_TYPE")
private String idType;
#CsvBindByName(column = "STUDY_ID")
private String studyId;
#CsvBindByName(column = "STUDY_NAME")
private String studyName;
}
pom.xml
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.3</version>
</dependency>
For more details, please visit openscv

Java Jackson deserialize an object containing a list of object with/without custom Deserializer?

I've got a JSON input like this
{
"slices": [{
"slice": {
"boundedBy": {
"Envelope": {
"axisLabels": "Lat Long ansi",
"lowerCorner": "-44.975 111.975 \"2003-01-01T00:00:00+00:00\"",
"upperCorner": "-8.975 155.975 \"2003-01-01T00:00:00+00:00\"",
"srsDimension": 3
}
},
"fileReferenceHistory": "/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20030101-20030110-H01V06-1.0_MERIS-FR-LAI-HA.tiff",
"local_metadata_key": "value_1"
}
},
{
"slice": {
"boundedBy": {
"Envelope": {
"axisLabels": "Lat Long ansi",
"lowerCorner": "-44.975 111.975 \"2003-10-01T00:00:00+00:00\"",
"upperCorner": "-8.975 155.975 \"2003-10-01T00:00:00+00:00\"",
"srsDimension": 3
}
},
"fileReferenceHistory": "/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20031001-20031010-H00V10-1.0_MERIS-FR-LAI-HA.tiff",
"local_metadata_key": "value_2"
}
}
],
"Title": "Drought code",
// other keys:values
}
with "slices" is an array of "slice" objects. Out of "slices" is any "keys":"values" but it is not the problem.
Then, I have a POJO class
public class CoverageMetadata {
#JsonProperty(value = "slices")
#JacksonXmlElementWrapper(useWrapping = false)
private List<LocalMetadata> localMetadataList;
private Map<String, String> globalMetadataAttributesMap;
#JsonAnySetter
public void addKeyValue(String key, String value) {
this.globalMetadataAttributesMap.put(key, value);
}
#JsonAnyGetter
public Map<String, String> getGlobalAttributesMap() {
return globalMetadataAttributesMap;
}
// other gettters, setters without Jackson annotations
}
and a class inside the list:
public class LocalMetadata {
public static final String LOCAL_METADATA_TAG = "slice";
private Map<String, String> localMetadataAttributesMap;
private BoundedBy boundedBy;
#JsonAnySetter
// NOTE: To map an unknown list of properties, must use this annotation
public void addKeyValue(String key, String value) {
this.localMetadataAttributesMap.put(key, value);
}
public LocalMetadata() {
this.localMetadataAttributesMap = new LinkedHashMap<>();
this.boundedBy = new BoundedBy();
}
#JsonAnyGetter
// NOTE: to unwrap the "map" from { "map": { "key": "value" } }, only keep { "key": "value" }
public Map<String, String> getLocalMetadataAttributesMap() {
return localMetadataAttributesMap;
}
public BoundedBy getBoundedBy() {
return this.boundedBy;
}
public void setBoundedBy(BoundedBy boundedBy) {
this.boundedBy = boundedBy;
}
public LocalMetadata(Map<String, String> localMetadataAttributesMap, BoundedBy boundedBy) {
this.localMetadataAttributesMap = localMetadataAttributesMap;
this.boundedBy = boundedBy;
}
}
And the basic code to deserialize JSON to object
ObjectMapper objectMapper = new ObjectMapper();
CoveageMetadata coverageMetadata = objectMapper.readValue(metadata, CoverageMetadata.class);
When I try to deserialize the JSON input to CoverageMetadata object, I got the error
Cannot deserialize coverage's metadata in XML/JSON by Jackson, error: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: {"slices":[{"slice":{"boundedBy":{"Envelope":{"axisLabels":"Lat Long ansi","srsDimension":3,"lowerCorner":"-44.975 111.975 \"2003-01-01T00:00:00+00:00\"","upperCorner":"-8.975 155.975 \"2003-01-01T00:00:00+00:00\""}},"local_metadata_key":"value_1","fileReferenceHistory":"/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20030101-20030110-H01V06-1.0_MERIS-FR-LAI-HA.tiff"}}],"Title":"Drought code"}; line: 1, column: 21] (through reference chain: petascope.core.gml.metadata.model.CoverageMetadata["slices"]->java.util.ArrayList[0]->petascope.core.gml.metadata.model.LocalMetadata["slice"]).
How can I deserialize this JSON input String to CoverageMetadataObject with each "slice" element will be mapped to a LocalMetadata object?
The simple answer is I create another POJO class to hold the "slices" list, in CoverageMetadata class, it will have
public class CoverageMetadata {
private Map<String, String> globalMetadataAttributesMap;
#JsonProperty(value = "slices")
private LocalMetadata localMetadata;
...
}
New POJO class (class LocalMetadata before was renamed to LocalMetadataChild)
public class LocalMetadata {
#JsonProperty(value = "slice")
// This is the most important thing to avoid duplicate <slices><slices> when serializing in XML.
#JacksonXmlElementWrapper(useWrapping = false)
private List<LocalMetadataChild> localMetadataList;
public LocalMetadata(List<LocalMetadataChild> localMetadataList) {
this.localMetadataList = localMetadataList;
}
public LocalMetadata() {
this.localMetadataList = new ArrayList<>();
}
public List<LocalMetadataChild> getLocalMetadataList() {
return localMetadataList;
}
public void setLocalMetadataList(List<LocalMetadataChild> localMetadataList) {
this.localMetadataList = localMetadataList;
}
}

Jackson serialization key and value from one object

I am trying to create a custom serializer to generate Pair object but I want to avoid "key" and "value" fields when the object is serialized.
Object pojo:
public class TypeObjectPair implements Serializable {
private final String canonicalObjectName;
private final Object object;
public String getKey() {
return canonicalObjectName;
}
public Object getValue() {
return object;
}
}
Person class. (Theoretically could be any other object class)
class Person{
int id;
String name;
}
Final object to serialize:
TypeObjectPair obj = new TypeObjectPair("com.example.Person", new Person(1, "Peter"));
Required output:
{
"com.example.object" : {
"id" : 1,
"name" : "Peter"
}
}
Any ideas on how to achieve it?
You could use a Map<K, V> with #JsonAnyGetter:
public class TypeObjectPair {
private Map<String, Object> data = new HashMap<>();
public TypeObjectPair(String key, Object value) {
data.put(key, value);
}
#JsonAnyGetter
public Map<String, Object> getData() {
return data;
}
}
Then use as follows:
ObjectMapper mapper = new ObjectMapper();
TypeObjectPair pair = new TypeObjectPair("com.example.object", new Person(1, "Peter"));
String json = mapper.writer().withDefaultPrettyPrinter().writeValueAsString(pair);
The output will be:
{
"com.example.object" : {
"id" : 1,
"name" : "Peter"
}
}

Deserializing a JSON array using Jackson

I am getting a JSON response from 3rd Party service provider and it has a array of objects in it.
When i am trying to deserialize JSON using Jackson api's. I am getting following exception
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of JacksonFields out of START_ARRAY token
at [Source: java.io.BufferedReader#1015a9e; line: 5, column: 26]
My JSON response is
{
"flags" : 1074200577,
"results" : {
"id1" : 0,
"id2" : 0,
"fields" : [
{
"id1" : 19202,
"id2" : 19202,
"count" : 0,
"format" : 8,
"type" : "name",
"flags" : 0,
"group" : 1074,
"value" : "1074"
},
{
"id1" : 19218,
"id2" : 19218,
"count" : 0,
"format" : 8,
"type" : "name",
"flags" : 0,
"group" : 1075,
"value" : "1075"
}
]
}
}
And my POJO class looks like this
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
class JacksonFields {
int id1;
int id2;
int count;
int format;
String type;
int flags;
int group;
String value;
public JacksonFields(){
}
#JsonCreator
public JacksonFields(#JsonProperty("id1") int id1,
#JsonProperty("id2") int id2,
#JsonProperty("count") int count,
#JsonProperty("format") int format,
#JsonProperty("type") String type,
#JsonProperty("flags") int flags,
#JsonProperty("group") int group,
#JsonProperty("value") String value){
this.id1 = id1;
this.id2 = id2;
this.count = count;
this.format = format;
this.type = type;
this.flags = flags;
this.group = group;
this.value = value;
}
public void putId1(int id){
this.id1=id;
}
public void putId2(int id){
this.id2=id;
}
public void putCount(int count){
this.count=count;
}
public void putFormat(int format){
this.format=format;
}
public void putType(String type){
this.type=type;
}
public void putFlag(int flag){
this.flags=flag;
}
public void putGroup(int group){
this.group=group;
}
public void putValue(String val){
this.value=val;
}
}
class JacksonResults {
int id1;
int id2;
JacksonFields fields;
#JsonCreator
public JacksonResults(#JsonProperty("id1") int id1,
#JsonProperty("id2") int id2,
#JsonProperty("fields") JacksonFields fields){
this.id1 = id1;
this.id2 = id2;
this.fields = fields;
}
public JacksonResults(){
}
public void putId1(#JsonProperty("id1") int id){
this.id1 = id;
}
public void putId2(#JsonProperty("id2") int id){
this.id2 = id;
}
public void putFields(#JsonProperty("fields") JacksonFields fie){
this.fields = fie;
}
}
public class JacksonJsonObj{
Long flags;
JacksonResults res;
#JsonCreator
public JacksonJsonObj(#JsonProperty("flags") long flags,
#JsonProperty("results") JacksonResults res){
this.flags = flags;
this.res = res;
}
public JacksonJsonObj(){
}
public void putFlags(#JsonProperty("flags") long flag){
this.flags = flag;
}
public void putResults(#JsonProperty("results") JacksonResults res){
this.res=res;
}
}
I am trying to deserialize JSON using following code
ObjectMapper objmapper = new ObjectMapper();
objmapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JacksonJsonObj jackobj = objmapper.readValue(new BufferedReader(new inputStreamReader(ipStream)), JacksonJsonObj.class);
if i try to do
JacksonJsonObj[] jackobj = objmapper.readValue(new BufferedReader(new inputStreamReader(ipStream)), JacksonJsonObj[].class);
it fails at the BEGIN_OBJECT itself.
How to read and deserialize the JSON wiht Arrays. Should i write my own deserializer?
EDIT
If i work on JSON String rather than stream i am able to get all Java objects back. But for better performance i want Jackson to work on stream
Alternate way
List<JsonFields> JsonFieldsJackson = new ArrayList<JsonFields>();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JsonNode nodes = mapper.readTree(strbuffer.toString());
nodes.elements();
Iterator<JsonNode> iter = nodes.path("results").path("fields").elements();
while(iter.hasNext()){
JsonNode node = iter.next();
JsonFields fie = mapper.readValue(node.toString(),JsonFields.class);
JsonFieldsJackson.add(fie);
}
I am considering that you already have 2 jars i.e.
1. Jackson Core
2. Jackson Mapper
So for Parsing from JSON to Your POJO
ObjectMapper mapper = new ObjectMapper();
JavaType javaType=mapper.getTypeFactory().constructType(JacksonFields.class);
JacksonFields jksnflds = mapper.readValue(jsonString,javaType);
and thats it !.
To deserialize the JSON you should have 3 class like
class Field{
int id1;
int id2;
int count;
int format;
String type;
int flags;
int group;
String value;
}
class Result{
int id1;
int id2;
Field[] fields;
}
class JacksonFields {
String flags;
Result result;
}
Then you can write code like
JacksonFields jackobj = objmapper.readValue(new BufferedReader(new inputStreamReader(ipStream)), JacksonFields.class);
Then it will work.
Note:-I did not provide proper annotation to the classes you can provide those.

Categories