Jackson csv - use semicolon(;) to deserialize as a string list - java

I'm using jackson csv to parse a csv as pojo
ID,requestId,requestSource,documentIds,trackingIds
documentIds,123456,CLAIMS,123456;223456,
->
#Data
#NoArgsConstructor
#JacksonXmlRootElement(localName = "triggerDocumentExport",namespace = Connection.NAMESPACE_CAS)
public class TriggerDocumentExport {
private Wrapper in;
public TriggerDocumentExport(Wrapper in){this.in = in;}
#Data
public static class Wrapper{
private String requestId,
requestSource;
private List<String> documentIds,
trackingIds;
}
}
I want documentIds to be parsed as a List<String>, with default ArrayElementSeparator(which is ;)
but it keeps parsing it as a single string "123456;223456"
without DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, I got an exception
with the configuration, I got a List with only one element "123456;223456"
If I don't make mistake, should jackson csv support semicolon-seperated list by default?Or there's something I've misunderstood.

Related

Deserializing JSON objects wrapped inside unnamed root object using Jackson

I have to work with an API that returns all objects wrapped in a unnamed root object. Something like this:
{
"user": {
"firstname":"Tom",
"lastname":"Riddle"
}
}
Here, I am interested in deserializing the user object only. But given the nature of the response, I will have to write a class that wraps the user object if I want to deserialize it successfully.
#Getter
#Setter
#ToString
// Wrapper class
public class Info {
private User user;
}
and then
#Getter
#Setter
#ToString
public class User {
private String firstname;
private String lastname;
}
All responses of the API return the response in this manner, so I am looking for a way to deserialize the response in such a way as to have one generic wrapper class that can be used to extract any type of JSON object.
I have tried this:
#Getter
#Setter
public class ResponseWrapper<T> {
private T responseBody;
}
and then
ResponseWrapper<User> userInfo = objectMapper.readValue(response.body().string(), ResponseWrapper.class);
But this results in the following exception:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "user" (class com.redacted.response.ResponseWrapper), not marked as ignorable (one known property: "responseBody"])
So, is there any way for me to deserialize this response without having to write separate wrapper classes for each API response like this?
You can do something like this:
JsonNode jsonNode = objectMapper.readTree(response.body().string());
String content = jsonNode.elements().next().toString();
User user = objectMapper.readValue(content, User.class);
Output:
User(firstname=Tom, lastname=Riddle)

How to correctly map huge json file to Java (pojo)?

Large json files are available (from 100 MB to 2 GB).
How I can create java (pojo) from json? I need to get the names of all fields. For example, one class can have more than 1000 fields.
Tried the following libraries & online services:
JsonSchema2Pojo works well, but has a limit of about 50,000 characters at a time. Due to the presence of limits, I cannot completely map the class. Need to partially copy the json each time and then remove the duplicate fields.
http://www.jsonschema2pojo.org/
JsonToJava
https://github.com/astav/JsonToJava
Also tried several other online services. They also have limits or do not work correctly.
Example of json file:
{"type":"FeatureCollection","features":[
{"type":"Feature","geometry":{"type":"Point","coordinates":[27.5618791,53.902334]},"properties":{"ele":"280","name":"Минск","place":"city","capital":"yes","name:ar":"مينسك","name:be":"Мінск","name:bg":"Минск","name:bo":"མིན་སིཀ།","name:cs":"Minsk","name:cu":"Мѣньскъ","name:cv":"Минск","name:de":"Minsk","name:el":"Μινσκ","name:en":"Minsk","name:eo":"Minsko","name:es":"Minsk","name:et":"Minsk","name:fa":"مینسک","name:fi":"Minsk","name:fr":"Minsk","name:ga":"Minsc","name:gl":"Minsk - Мінск","name:he":"מינסק","name:hi":"मिन्‍स्‍क","name:hr":"Minsk","name:hu":"Minszk","name:hy":"Մինսկ","name:ia":"Minsk","name:io":"Minsk","name:is":"Minsk","name:it":"Minsk","name:ja":"ミンスク","name:ka":"მინსკი","name:kk":"Минск","name:kn":"ಮಿನ್ಸ್ಕ್","name:ko":"민스크","name:ku":"Mînsk","name:kv":"Минск","name:ky":"Минск","name:la":"Minscum","name:lt":"Minskas","name:lv":"Minska","name:mk":"Минск","name:ml":"മിൻസ്ക്","name:mr":"मिन्‍स्‍क","name:nl":"Minsk","name:no":"Minsk","name:oc":"Minsk","name:os":"Минск","name:pl":"Mińsk","name:pt":"Minsk","name:ru":"Минск","name:sk":"Minsk","name:sl":"Minsk","name:sr":"Минск","name:sv":"Minsk","name:ta":"மின்ஸ்க்","name:tg":"Минск","name:th":"มินสก์","name:tt":"Минск","name:ug":"مىنىسكى","name:uk":"Мінськ","name:ur":"منسک","name:vi":"Minxcơ","name:vo":"Minsk","name:yi":"מינסק","name:zh":"明斯克","website":"https://minsk.gov.by/","int_name":"Minsk","name:ast":"Minsk","name:ckb":"مینسک","name:csb":"Mińsk","name:jbo":"misk","name:mhr":"Минск","name:myv":"Минск ош","name:nds":"Minsk","name:pnb":"منسک","name:rue":"Мінск","name:sah":"Минскай","name:szl":"Mińsk","name:udm":"Минск","name:wuu":"明斯克","nat_name":"Мінск","old_name":"Менск","wikidata":"Q2280","wikipedia":"ru:Минск","population":"1982444","admin_level":"2","alt_name:be":"Менск","alt_name:vi":"Minsk;Minxcơva","name:prefix":"город","old_name:be":"Менск","addr:country":"BY","name:bat-smg":"Minsks","name:sr-Latn":"Minsk","wikipedia:be":"Мінск","wikipedia:en":"Minsk","wikipedia:pl":"Mińsk","addr:postcode":"220000","is_in:country":"Belarus","name:be-tarask":"Менск","source:name:oc":"Lo Congrès","is_in:continent":"Europe","population:date":"2018-01-01","capital_ISO3166-1":"yes","source:population":"Белстат","is_in:country_code":"BY"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5861178,53.9510657],[27.5861196,53.9510294],[27.5862319,53.9510313],[27.5862302,53.9510676],[27.5861178,53.9510657]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5885075,53.9512721],[27.5885398,53.9511614],[27.5887363,53.9511813],[27.588704,53.9512919],[27.5885075,53.9512721]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5881428,53.9512622],[27.5881704,53.9511135],[27.588421,53.9511296],[27.5883935,53.9512783],[27.5881428,53.9512622]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5892179,53.9516538],[27.5893274,53.9516011],[27.5893778,53.9516374],[27.5894352,53.9516098],[27.5895358,53.9516823],[27.5893689,53.9517626],[27.5892179,53.9516538]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.588949,53.9517486],[27.5891273,53.9516621],[27.5892764,53.9517686],[27.5890981,53.9518551],[27.588949,53.9517486]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5867595,53.9500825],[27.5867648,53.9499951],[27.5869291,53.9499985],[27.5869238,53.9500859],[27.5867595,53.9500825]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5830382,53.9503042],[27.5830422,53.9502013],[27.5832783,53.9502045],[27.5832743,53.9503074],[27.5830382,53.9503042]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5820906,53.9497446],[27.5820973,53.9496721],[27.5822371,53.9496765],[27.5822305,53.949749],[27.5820906,53.9497446]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5477403,53.8940388],[27.5482144,53.8939744],[27.5482459,53.8940791],[27.5482929,53.8940736],[27.5483083,53.8941424],[27.5482593,53.8941471],[27.5482741,53.8942048],[27.5485718,53.8943067],[27.5487113,53.8943028],[27.5487556,53.8943755],[27.548895,53.8944261],[27.5487985,53.894513],[27.5488079,53.8945841],[27.5483385,53.8943889],[27.548317,53.8943202],[27.5481439,53.8942549],[27.5481045,53.8941843],[27.5479863,53.8942063],[27.5479953,53.8942214],[27.5478248,53.8942506],[27.5477403,53.8940388]]]]},"properties":{"name":"Инженерный корпус метрополитена","building":"yes"}}
]}
Thanks in advance!
Thanks a lot for your advices.
Implemented in the following way:
I used JsonAnySetter annotation to set all fields instead creating pojo with all of the possible fields.
Here is my Dto's
FeatureDto
#Getter
#ToString
public class FeatureDto {
#JsonProperty("type")
private String type;
#JsonProperty("geometry")
private GeometryDto geometry;
#JsonProperty("properties")
private PropertiesDto properties;
}
PropertiesDto
#Getter
#ToString
public class PropertiesDto {
private List<FieldDto> fieldDtos = new ArrayList<>();
#JsonAnySetter
public void setProperties(String code, Object value)
{
if(value instanceof ArrayList) {
ArrayList<Object> list = (ArrayList<Object>) value;
StringBuffer stringBuffer = new StringBuffer();
list.forEach(o -> stringBuffer.append(o).append(", "));
fieldDtos.add(new FieldDto(code, stringBuffer.toString()));
return;
}
fieldDtos.add(new FieldDto(code, value.toString()));
}
}
FieldDto
#Data
#ToString
#JsonIgnoreProperties(ignoreUnknown = true)
#AllArgsConstructor
public class FieldDto {
#JsonProperty("code")
private String code;
#JsonProperty("value")
private String value;
}
Here is the json source:
{"type":"FeatureCollection","features":[
{"type":"Feature","geometry":{"type":"Point","coordinates":[27.5618791,53.902334]},"properties":{"ele":"280","name":"Минск","place":"city","capital":"yes","name:ar":"مينسك","name:be":"Мінск","name:bg":"Минск","name:bo":"མིན་སིཀ།","name:cs":"Minsk","name:cu":"Мѣньскъ","name:cv":"Минск","name:de":"Minsk","name:el":"Μινσκ","name:en":"Minsk","name:eo":"Minsko","name:es":"Minsk","name:et":"Minsk","name:fa":"مینسک","name:fi":"Minsk","name:fr":"Minsk","name:ga":"Minsc","name:gl":"Minsk - Мінск","name:he":"מינסק","name:hi":"मिन्‍स्‍क","name:hr":"Minsk","name:hu":"Minszk","name:hy":"Մինսկ","name:ia":"Minsk","name:io":"Minsk","name:is":"Minsk","name:it":"Minsk","name:ja":"ミンスク","name:ka":"მინსკი","name:kk":"Минск","name:kn":"ಮಿನ್ಸ್ಕ್","name:ko":"민스크","name:ku":"Mînsk","name:kv":"Минск","name:ky":"Минск","name:la":"Minscum","name:lt":"Minskas","name:lv":"Minska","name:mk":"Минск","name:ml":"മിൻസ്ക്","name:mr":"मिन्‍स्‍क","name:nl":"Minsk","name:no":"Minsk","name:oc":"Minsk","name:os":"Минск","name:pl":"Mińsk","name:pt":"Minsk","name:ru":"Минск","name:sk":"Minsk","name:sl":"Minsk","name:sr":"Минск","name:sv":"Minsk","name:ta":"மின்ஸ்க்","name:tg":"Минск","name:th":"มินสก์","name:tt":"Минск","name:ug":"مىنىسكى","name:uk":"Мінськ","name:ur":"منسک","name:vi":"Minxcơ","name:vo":"Minsk","name:yi":"מינסק","name:zh":"明斯克","website":"https://minsk.gov.by/","int_name":"Minsk","name:ast":"Minsk","name:ckb":"مینسک","name:csb":"Mińsk","name:jbo":"misk","name:mhr":"Минск","name:myv":"Минск ош","name:nds":"Minsk","name:pnb":"منسک","name:rue":"Мінск","name:sah":"Минскай","name:szl":"Mińsk","name:udm":"Минск","name:wuu":"明斯克","nat_name":"Мінск","old_name":"Менск","wikidata":"Q2280","wikipedia":"ru:Минск","population":"1982444","admin_level":"2","alt_name:be":"Менск","alt_name:vi":"Minsk;Minxcơva","name:prefix":"город","old_name:be":"Менск","addr:country":"BY","name:bat-smg":"Minsks","name:sr-Latn":"Minsk","wikipedia:be":"Мінск","wikipedia:en":"Minsk","wikipedia:pl":"Mińsk","addr:postcode":"220000","is_in:country":"Belarus","name:be-tarask":"Менск","source:name:oc":"Lo Congrès","is_in:continent":"Europe","population:date":"2018-01-01","capital_ISO3166-1":"yes","source:population":"Белстат","is_in:country_code":"BY"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5861178,53.9510657],[27.5861196,53.9510294],[27.5862319,53.9510313],[27.5862302,53.9510676],[27.5861178,53.9510657]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5885075,53.9512721],[27.5885398,53.9511614],[27.5887363,53.9511813],[27.588704,53.9512919],[27.5885075,53.9512721]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5881428,53.9512622],[27.5881704,53.9511135],[27.588421,53.9511296],[27.5883935,53.9512783],[27.5881428,53.9512622]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5892179,53.9516538],[27.5893274,53.9516011],[27.5893778,53.9516374],[27.5894352,53.9516098],[27.5895358,53.9516823],[27.5893689,53.9517626],[27.5892179,53.9516538]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.588949,53.9517486],[27.5891273,53.9516621],[27.5892764,53.9517686],[27.5890981,53.9518551],[27.588949,53.9517486]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5867595,53.9500825],[27.5867648,53.9499951],[27.5869291,53.9499985],[27.5869238,53.9500859],[27.5867595,53.9500825]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5830382,53.9503042],[27.5830422,53.9502013],[27.5832783,53.9502045],[27.5832743,53.9503074],[27.5830382,53.9503042]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5820906,53.9497446],[27.5820973,53.9496721],[27.5822371,53.9496765],[27.5822305,53.949749],[27.5820906,53.9497446]]]]},"properties":{"building":"yes"}},
{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[27.5477403,53.8940388],[27.5482144,53.8939744],[27.5482459,53.8940791],[27.5482929,53.8940736],[27.5483083,53.8941424],[27.5482593,53.8941471],[27.5482741,53.8942048],[27.5485718,53.8943067],[27.5487113,53.8943028],[27.5487556,53.8943755],[27.548895,53.8944261],[27.5487985,53.894513],[27.5488079,53.8945841],[27.5483385,53.8943889],[27.548317,53.8943202],[27.5481439,53.8942549],[27.5481045,53.8941843],[27.5479863,53.8942063],[27.5479953,53.8942214],[27.5478248,53.8942506],[27.5477403,53.8940388]]]]},"properties":{"name":"Инженерный корпус метрополитена","building":"yes"}}
]}

serialize and deserialize without map name

I have the following Object:
public class Class_a{
private List<class_b> someList;
}
public class Class_b{
private Map<String,String> someMap;
}
My json will look like this:
"someList":[{"someMap":{"strKey1":"strValue1"}},{"someMap":{"strKey2":"strValue2"}}]
Is it possible to serialize a Json that will look like this, without changing my Objects (and I will have the option to deserialize the Object):
"someList":[{"strKey1":"strValue1"},{"strKey2":"strValue2"}]
*I know that if will defined my object like this:
public class Class_a{
private List<Map<Strung,String>> someList;
}
i will get a Json like I want - but I am trying to find more elegant solution then 'list' that contain a 'map'
My project use spring framework and Jackson.
This worked for me I only had to add getters and setters to your classes and I was able to parse with jackson:
#Test
public void t() throws IOException {
String json = "{\"someList\":[{\"someMap\":{\"strKey1\":\"strValue1\"}},{\"someMap\":{\"strKey2\":\"strValue2\"}}]}";
Class_a a = new ObjectMapper().readValue(json, Class_a.class);
System.out.println(a);
}
#Getter
#Setter
public class Class_a{
private List<Class_b> someList;
}
#Getter
#Setter
public class Class_b{
private Map<String,String> someMap;
}
I'm using lombok but that's nothing special, you can create the getters/setters manually too and will work

Java, How can I use Jackson ObjectMapper to deserialize a double nested json list

I'm trying to deserialize json objects with the following structure:
{"results":{
"Assessments":{
"Assessment":[
{
"assessor":"",
"buildingName":"Emerald Palace Project",
"certBody":"",
...
The top level is a single entity named "results" which contains "assessments" which are just a list/array of "assessment."
I've tried multiple combinations of mapper configuration such as:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
But no matter how I switch it up I keep getting a Results object with null Assessments.
Here are my object classes using Lombok.
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
static class Results {
private Assessments assessments;
}
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
static class Assessments {
private List<Assessment> assessments;
}
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Assessment {
private int parentId;
private String stage;
private String notes;
private String rating;
private String scheme;
}
I feel like I must be missing a piece.
Any insight would be greatly appreciated.
Just to be clear: you wrote that
[…] "assessments" which are just a list/array of "assessment."
and your POJOs reflect that... then your JSON has to be…
{"results":{
"Assessments":{
[
{
"assessor":"",
"buildingName":"Emerald Palace Project",
"certBody":"",
...
…instead of…
{"results":{
"Assessments":{
"Assessment":[
{
"assessor":"",
"buildingName":"Emerald Palace Project",
"certBody":"",
...
Watch out for the list directly in "Assessments".
Also mind that your POJO fields are lowercase and so have to be your JSON keys.
So to match POJO with JSON you have various options:
change your JSON keys to lowercase and camelcase
use #JsonProperty("field-name") to match your JSON keys
…
But in each case you have to be aware of the current clash regarding the Assessments/Assessments list.
So because I had to work with the json given to me by the third party API, altering the json was not an option.
Here's how I got this working.
First off I had to change the Assessments object to have a list with a singular name. "assessment" instead of "assessments" as that is how it was spelled in the json response.
#Getter
#Setter
#NoArgsConstructor
static class Assessments {
private List<Assessment> assessment;
}
Also I set up my ObjectMapper to ignore case and unknown properties. Making sure to use com.fasterxml.jackson.databind.ObjectMapper.
private static ObjectMapper getJsonMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
return mapper;
}
The biggest change however was the introduction of a container class.
#Getter
#Setter
#NoArgsConstructor
private static class JsonContainer {
private Results results;
}
This class was required as it held the top level json object "Results."
After these changes were in place I got the Java objects in the state I expected.

How to use Jackson Annotation to do a mapping for deserialization

I'm using Jackson CSV to parse a CSV file into POJOs, like this.
List<SomeThing> something = csvMapper.readerFor(SomeThing.class).with(emptySchema().withHeader()).readValue(filecsv);
My issue is that I would like wrap my SomeThing list on a root Object, like this.
#JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use =
JsonTypeInfo.Id.NAME)
public class SomeThingWrapper extends BaseDto {
#JsonProperty("something")
private List<something> somethings;
}
So the previous code can be write like this :
SomeThingWrapper somethingWrapper = csvMapper.readerFor(somethingWrapper.class).with(emptySchema().withHeader()).readValue(filecsv);
My SomeThing POJO
#JsonRootName("SomeThing")
public class SomeThing {
#JsonProperty("ID")
private String id;
}
How would you suggest to be the best way to do this?

Categories

Resources