ModelMapper attribute fields with correlation names, in camel case - java

Error converting entity with source attribute name content in source fiels with camel case part
Example: in source model i heve a String field edgeId, and in target model i heve a field Long id, the match is true. This generate a exception, java.lang.NumberFormatException, how to ignore this match.
This is occurre with another attribute names
package br.com.combinado;
import org.modelmapper.ModelMapper;
public class TestModelMapper {
public static void main(String[] args) {
Target target = new Target();
target.setTesteBatataFrita("batataFrinta");
ModelMapper mapper = new ModelMapper();
Source source = mapper.map(target, Source.class);
System.out.println(source);
}
private static class Source {
private Long frita;
public Long getFrita() {
return frita;
}
public void setFrita(Long frita) {
this.frita = frita;
}
}
private static class Target {
private String testeBatataFrita;
public String getTesteBatataFrita() {
return testeBatataFrita;
}
public void setTesteBatataFrita(String testeBatataFrita) {
this.testeBatataFrita = testeBatataFrita;
}
}
}

I solved by adding a add a SourceNameTokenizer
mapper.getConfiguration().setSourceNameTokenizer(new NameTokenizer() {
public String[] tokenize(String name, NameableType nameableType) {
return new String[] { name };
}
});
Or
#Bean
public ModelMapper modelMapper() {
final ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setDestinationNameTokenizer((name, nameableType) -> new String[] { name });
mapper.getConfiguration().setSourceNameTokenizer((name, nameableType) -> new String[] { name });
return mapper;
}

Old question but in latest versions I found a way to solve it with
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

Related

Can I tell Jackson to conditionally serialize a private instance variable based on differently-typed method?

To the best of my understanding, Jackson will
serialize a public instance variable to the variable name
public List<String> myStrings = new ArrayList<>();
serializes to
{ 'myStrings' : [ ... ] }
serialize a private instance variable to the variable name if it has a public getter named getVariable():
private List<String> myStrings = new ArrayList<>();
public List<String> getMyStrings() { return myStrings; }
serializes similar to
{ 'myStrings' : [ ... ] }
However, what I am trying to achieve is to serialize it to a String (instead of array of Strings) based on another method, but keep the JSON key (based on #JsonInclude(JsonInclude.Include.NON_NULL) suppressing the original accessor in some cases
#JsonInclude(JsonInclude.Include.NON_NULL)
private boolean firstStringOnly = true;
private List<String> myStrings = new ArrayList<>();
public List<String> getMyStrings() { return firstStringOnly ? null: myStrings; }
public String getFirstString() { return firstStringOnly ? myStrings.get(0) : null; }
Desired JSON serialization:
For firstStringOnly==true: { 'myStrings' : 'first_String' } (using getFirstString())
For firstStringOnly==false: { 'myStrings' : [ ... ] } (using getMyStrings())
Is this possible to do? I'm specifically looking to avoid using custom serializers, and do this via annotations only.
You can assume a reasonably recent version of Jackson and Java 8.
Just to re-iterate, the question constraints are:
* NO custom serializer
* Both use cases produce the same JSON key
You can generalize getMyStrings() method and make it return Object. And inside check the flag and return first value or all values. Here is my sample
public class tst {
private static class YourObject {
private boolean firstStringOnly;
private List<String> myStrings = new ArrayList<>();
public YourObject(boolean firstStringOnly) {
this.firstStringOnly = firstStringOnly;
this.myStrings.add("str1");
this.myStrings.add("str2");
}
public Object getMyStrings(){
return firstStringOnly ? myStrings.get(0) : myStrings;
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(new YourObject(true)));
System.out.println(mapper.writeValueAsString(new YourObject(false)));
}
}
The output is
{"myStrings":"str1"}
{"myStrings":["str1","str2"]}
EDIT: Sorry, i have misread your initial question. I assume you want to keep both of the typed getters. Would this work for you?
public class TestClass {
private boolean firstStringOnly = true;
private List<String> myStrings = new ArrayList<>();
#JsonIgnore
public boolean isFirstStringOnly() {
return firstStringOnly;
}
public void setFirstStringOnly(boolean firstStringOnly) {
this.firstStringOnly = firstStringOnly;
}
#JsonIgnore
public List<String> getMyStrings() {
return firstStringOnly ? null : myStrings;
}
#JsonIgnore
public String getFirstString() { return firstStringOnly ? myStrings.get(0) : null; }
#JsonProperty("myStrings")
public Object getMyStringsForSerialization() {
return firstStringOnly ? getFirstString() : getMyStrings();
}
public void setMyStrings(List<String> myStrings) {
this.myStrings = myStrings;
}

Jackson Deserializing From CSV to Enum

I'm trying to deserialize from a football results csv to an enum using Jackson's dataformat library. This is the csv file (the sixth column is the one I'm interested in):
Egypt,Uruguay,GROUP,2,0,HOME
This is my enum class:
#JsonIgnoreProperties(ignoreUnknown = true)
public enum MatchOutcome {
HOME(3, 0),
DRAW(1, 1),
AWAY(0, 3),
HOME_ET(1, 1),
AWAY_ET(1, 1),
HOME_PENS(1, 1),
AWAY_PENS(1, 1);
private final Integer homePoints;
private final Integer awayPoints;
MatchOutcome(Integer homePoints, Integer awayPoints) {
this.homePoints = homePoints;
this.awayPoints = awayPoints;
}
public Integer homePoints() {
return this.homePoints;
}
public Integer awayPoints() {
return this.awayPoints;
}
}
And this is the main method:
public static void main(String[] args) throws Exception {
CsvSchema csvSchema = CsvSchema.builder()
.addColumn("HOME")
.addColumn("AWAY")
.addColumn("STAGE")
.addColumn("HOME_FULL_TIME")
.addColumn("AWAY_FULL_TIME")
.addColumn("MATCH_OUTCOME")
.build();
CsvMapper csvMapper = new CsvMapper();
File csvFile = new File("src/Resources/fixtureResult.csv");
MappingIterator<MatchOutcome> matchOutcomeIterator = csvMapper.readerFor(MatchOutcome.class).with(csvSchema)
.readValues(csvFile);
while (matchOutcomeIterator.hasNextValue()) {
MatchOutcome matchOutcome = matchOutcomeIterator.nextValue();
System.out.println(matchOutcomeIterator.toString());
}
}
I'm getting the following error:
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.football.Calculator.MatchOutcome` out of START_OBJECT token
Are my annotations wrong? Or do I need a toString method on my Enum?
I created a wrapper class and mapped to that in the end,
#JsonIgnoreProperties(ignoreUnknown = true)
public class MatchOutcomeWrapper {
public MatchOutcome matchOutcome;
public MatchOutcomeWrapper(#JsonProperty("MATCH_OUTCOME") MatchOutcome matchOutcome) {
this.matchOutcome = matchOutcome;
}
public MatchOutcome getMatchOutcome() {
return matchOutcome;
}
public String toString() {
return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)
.append("matchOutcome", matchOutcome)
.toString();
}
}

Jackson -- deserialize JavaFX StringProperty type field with custom deserializer

Let's say my POJO is limited to the following:
public class TestPojo {
StringProperty myField;
public TestPojo(){}
public TestPojo(String myField) {
this.myField = new SimpleStringProperty(myField);
}
public String getMyField() {
return this.myField.get();
}
public StringProperty myFieldProperty() {
return this.myField;
}
public void setMyField(String myField) {
this.myField.set(myField);
}
}
I want to deserialize with Jackson. Jackson doesn't seem to like StringProperty, because as a normal String it works as expected. So I write a custom deserializer...
public class StringPropertyDeserializer extends JsonDeserializer<StringProperty> {
public StringPropertyDeserializer() {}
#Override
public StringProperty deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
String value = jsonParser.readValueAs(String.class);
return new SimpleStringProperty(value);
}
}
And I add this annotation to my StringProperty field...
#JsonDeserialize(using = StringPropertyDeserializer.class)
I get the following error:
com.fasterxml.jackson.databind.JsonMappingException: Class com.test.example.TestPojo$StringPropertyDeserializer has no default (no arg) constructor
I added a default constructor into the deserializer (as you can see above) and I get the same error regardless of it being there. Any solutions? This seems like it should be simple.
Edit here is the actual code where I'm making the call if that's helpful...
#GET("/api/test")
Call<List<TestPojo>> testPojoCall();
And it's configured in Gradle like so:
compile group: 'com.squareup.retrofit2', name: 'converter-jackson', version: '2.1.0'
That is everything related to this code.
Your POJO implementation isn't correct: the no-arg constructor doesn't initialize the StringProperty. Consequently, if you use the no-arg constructor, then call setMyField(...) you'd get a null pointer exception. I'm guessing that trying to work around that was what led you to try creating the custom deserializer.
I'm not entirely sure why the custom deserializer is giving the error it's giving (maybe it doesn't like the fact that it's an inner class: that's just a guess).
The following works fine for me without any custom deserialization:
TestPojo.java:
package jxtest;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class TestPojo {
private final StringProperty myField1 = new SimpleStringProperty();
private final StringProperty myField2 = new SimpleStringProperty();
private int myField3 ;
public final StringProperty myField1Property() {
return this.myField1;
}
public final String getMyField1() {
return this.myField1Property().get();
}
public final void setMyField1(final String myField1) {
this.myField1Property().set(myField1);
}
public final StringProperty myField2Property() {
return this.myField2;
}
public final String getMyField2() {
return this.myField2Property().get();
}
public final void setMyField2(final String myField2) {
this.myField2Property().set(myField2);
}
public int getMyField3() {
return myField3;
}
public void setMyField3(int myField3) {
this.myField3 = myField3;
}
}
Test.java:
package jxtest;
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public static void main(String[] args) throws IOException {
TestPojo item = new TestPojo();
item.setMyField1("Test1");
item.setMyField2("Test2");
item.setMyField3(42);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(item);
System.out.println(json);
TestPojo readBackIn = mapper.readValue(json, TestPojo.class);
System.out.println(readBackIn.getMyField1());
System.out.println(readBackIn.getMyField2());
System.out.println(readBackIn.getMyField3());
}
}
Output:
{"myField1":"Test1","myField2":"Test2","myField3":42}
Test1
Test2
42
Using jackson-databind 2.8.7.

Jackson: Serialize comma separated string to json array

Currently I have form like below:
public class Form {
private String listOfItems;
public String getListOfItems() {
return listOfItems;
}
public void setListOfItems(String listOfItems) {
this.listOfItems= listOfItems;
}
}
For instanse listOfItems equals to the following string "1,2,3".
The goal is to serialize this form to following format:
{
"listOfItems": [1, 2, 3]
}
It would be good to know how to correctly do such thing? As I know it is possible to create some custom serializer then mark appropriate getter method with it, like this #JsonSerialize(using = SomeCustomSerializer).
But not sure whether it is correct approach, probably any default implementations already exist.
If you can edit your Form class:
public class Form {
private String listOfItems;
public String getListOfItems() {
return listOfItems;
}
public void setListOfItems(String listOfItems) {
this.listOfItems = listOfItems;
}
#JsonProperty("listOfItems")
public List<Integer> getArrayListOfItems() {
if (listOfItems != null) {
List<Integer> items = new ArrayList();
for (String s : listOfItems.split(",")) {
items.add(Integer.parseInt(s)); // May throw NumberFormatException
}
return items;
}
return null;
}
}
By default Jackson looks for getters for serializing. You can override this by using #JsonProperty annotation.
ObjectMapper mapper = new ObjectMapper();
Form form = new Form();
form.setListOfItems("1,2,3");
System.out.print(mapper.writeValueAsString(form));
Outputs:
{"listOfItems":[1,2,3]}

BeanWriter Disable outputting empty lists

I have the following bean:
public class ContractBean {
private List<String> listNd;
private String nd;
public List<String> getListNd() {
return listNd;
}
public void setListNd(final List<String> listNd) {
this.listNd = listNd;
}
public String getNd() {
return nd;
}
public void setNd(final String nd) {
this.nd= nd;
}
}
I use apache Betwixt to output XML from my bean.
final BeanWriter beanWriter = new BeanWriter(outputWriter);
beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(false);
beanWriter.getBindingConfiguration().setMapIDs(false);
beanWriter.enablePrettyPrint();
beanWriter.setWriteEmptyElements(false);
beanWriter.getBindingConfiguration().setObjectStringConverter(new CustomObjectStringConverter());
beanWriter.write(obj);
The listND attribute of my bean is null, but i still get:
<contract>
<listNd/>
<nd>22222</nd>
</contract>
How can I remove empty lists from the output XML ?

Categories

Resources