I'm using Dozer to Map from one object to another. I know Dozer can do a recursive mapping, but maybe i'm putting too much pressure on Dozer :p I want to map from class A to B
class A {
private Map<String, List<ObjectA>> myMap;
// getters and setter for myMap
}
class B{
private Map<String, List<ObjectB>> myMap;
// getters and setter for myMap
}
When I map from A to B I get an instance of B, but inside the Map I got a List of ObjectA. To be clear, I get an instance of this (imaginary) object:
class B{
Map<String, List<ObjectA>> myMap;
}
How can I make dozer to perform this mapping correctly?
Note: ObjectA and ObjectB have the same properties (and int and a String).
You could specified hint:
<field>
<a>A</a>
<b>B</b>
<a-hint>ObjectA</a-hint>
<b-hint>ObjectB</b-hint>
</field>
Related
I have a class which it's only field is an HashMap.
Is it possible to define the #Id of the class to be one of the keys of the HashMap? (which always exists there)
Thanks!
If you have a Class that contains only an HashMap don't define a Class because it not make any sense, instead convert your query result directly in an Map likes Map<String, Object> dbCursor = mongoTemplate.getCollection("articles").find(query.getQueryObject(), Map.class).first();
I suggest you to use the Class in order to define your object, maybe you can use something like
public class Foo {
#Id
private String id;
private Map<String, Object> data;
private Map<String, Object> metadata;
}
in order to maintain flexibility
I have an IsoMessage object (https://github.com/chochos/j8583/blob/master/src/main/java/com/solab/iso8583/IsoMessage.java) that has an internal array which I can only access through a getField(int) method.
public class IsoMessage {
#SuppressWarnings("rawtypes")
private IsoValue[] fields = new IsoValue[129];
.........
.........
.........
/** Returns the IsoValue for the specified field. First real field is 2. */
#SuppressWarnings("unchecked")
public <T> IsoValue<T> getField(int field) {
return fields[field];
}
I need to read all the attributes stored on the fields array, by calling getField(param Number), and move them to a new object that has a Map, and want to achieve this using dozer.
the object that I need to translate to:
public class TransactionInstance implements Serializable {
private static final long serialVersionUID = 3429335891821913088L;
private String transactionName;
private Map<String, String> parameters;
I was experimenting with this dozer configuration hoping to get the field 1 from my isoMessage object
<mapping map-id="a">
<class-a>com.solab.iso8583.IsoMessage</class-a>
<class-b>j8583.example.TransactionInstance</class-b>
<field>
<a get-method="getField" key="1">field</a>
<b map-set-method="put">parameters</b>
</field>
</mapping>
But I'm stuck at getting the value from the original object with this exception:
Exception in thread "main" org.dozer.MappingException: No read or write method found for field (field) in class (class com.solab.iso8583.IsoMessage)
at org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.determinePropertyType(GetterSetterPropertyDescriptor.java:319)
at org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.getPropertyType(GetterSetterPropertyDescriptor.java:76)
at org.dozer.fieldmap.MapFieldMap.determineActualPropertyType(MapFieldMap.java:170)
at org.dozer.fieldmap.MapFieldMap.getSrcFieldValue(MapFieldMap.java:95)
I was checking this post https://github.com/DozerMapper/dozer/issues/111 and How to pass `this` to Dozer field mapping? bus still stuck in the same place, also I was wondering if I can achieve this by using the API so I can tell dynamically which fields I want to get from the original bean
I'm not familiar with Dozer, but field 1 is the bitmap. getField(1) returns null.
I finally foud the rigth mapping using the capability that dozer has to access the internal objects directly (http://dozer.sourceforge.net/documentation/custommethods.html).
<mapping>
<class-a is-accessible="true">com.solab.iso8583.IsoMessage</class-a>
<class-b>j8583.example.TransactionInstance</class-b>
<field>
<a>fields[3]</a>
<b set-method="addParameter" map-set-method="addParameter" key="field3">parameters
</b>
</field>
</mapping>
I have a entity like this:
public class MyEntity {
public Map map1;
public Map map2;
}
Using XStreams, I want to use the default map converter for map1 and my own map converter for map2. How can I do this?
Add an annotation in the field #XStreamConverter(MyOwnConverter.class) as shown here.
My object graph consists of Hibernate entities. Now most of the objects don't exist in the new database. However some do. So my object is like this:
Class MyObject{
Set<B> bset;
Set<C> cset;
}
The items in bset need to be instantiated and persisted after deserialization. However, the items in cset already exist in the new database, so I don't want new instances created. What is the best way to tell Jackson I know how to find references to these? Right now I am thinking about using a custom serializer / deserializer for cset, which will serialize it by creating an object with the database ID, and then will deserialize it by pulling the appropriate objects out of the database.
This is kind of complicated and I am hoping there is a simpler solution. Any suggestions?
Figured it out. There are three things I needed:
A JsonCreator to take the entityManager, and the id to return an object
#JsonCreator
#IgnoredMethod
public static UiElement findById(#JacksonInject EntityManager entityManager, #JsonProperty("id") int id) {
return entityManager.find(UiElement.class, id);
}
A JsonValue getter to return an object with only the id
#JsonValue
#Transient
public Map<String,Integer> getJsonObject(){
HashMap<String,Integer> map = new HashMap<String,Integer>();
map.put("id", getId());
return map;
}
The entity manager needed to be injected into the ObjectMapper
//entitymanager for creating any static data based entities
InjectableValues injects = new InjectableValues.Std().addValue(EntityManager.class, entityManager);
mapper.setInjectableValues(injects);
I have some beans, and they model (explicitly) the core data types in a JSon. However, sometimes the Jsons im reading have extra data in them.
Is there a way to annotate/define a Bean in jackson so that it uses explicit field names for some of the fields (the ones I know of, for example), while cramming the extra fields into a map / list ?
Yes there is, assuming you really do want to retain all the extra/unrecognized parameters, then do something like this:
public class MyBean {
private String field1;
private String field2;
private Integer field3;
private Map <String, Object> unknownParameters ;
public MyBean() {
super();
unknownParameters = new HashMap<String, Object>(16);
}
// Getters & Setters here
// Handle unknown deserialization parameters
#JsonAnySetter
protected void handleUnknown(String key, Object value) {
unknownParameters.put(key, value);
}
}
To configure global handling of parameters you can choose to define an implementation of DeserializationProblemHandler and register it globally with the ObjectMapper config.
DeserializationProblemHandler handler = new MyDeserializationProblemHandler();
ObjectMapper.getDeserializationConfig().addHandler(handler);
If you find you really do not care about the unknown parameters, then you can simply turn them off. On a per-class basis with the #JsonIgnoreProperties(ignoreUnknown = true), or globally by configuring ObjectMapper:
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false)