I am facing issue on deserializing pojo having field as interface which is implemented by multiple enum's
public interface interfaceEnum {
}
public enum a implements interfaceEnum {
A, B, C
}
public enum b implements interfaceEnum {
D, E, F
}
public class pojo {
public Integer id;
public interfaceEnum enum;
public Integer getId(){
return id;
}
public void setId(Integer id) {
this.id = id;
}
public intefaceEnum getInterfaceEnum() {
return interfaceEnum;
}
public void setIntefaceEnum(intefaceEnum enum){
this.interfaceEnum = enum;
}
}
I had also tried to implement custom deserializer by using
#JsonDeserialize of fasterxml.jackson on interfaceEnum but i am facing issue is Content
type 'application/json;charset=UTF-8' not supported
I need to pass json to pojo from UI side or using rest client, so i need to do both serializing and deserializing the interfaceEnum in pojo.
Thanks in advance for the help. :)
Related
I'm working on a project that requires me to serialize and deserialize generic objects. The way I'm going about this, is defining an abstract class Serializer that implements a toBytes() and a static fromBytes(). All is well with this approach, as I can pass an object instance to a generic class Foo that expects a Serializer subclass, and I can ensure the object knows how to serialize and deserialize itself.
Now my question. Java serialization kinda sucks. I have multiple implementations I'd like to try swapping in and out, and ultimately I'd like the user to be able to decide the format. How would I go about changing the implementation details of Serializer? I know I can't override static methods, so how would I do this without decoupling Foo and Serializer and not being able to ensure my generic object has the appropriate toBytes() and fromBytes() method in Foo?
Here is code if anyone is confused:
public abstract class Serializer {
public static Serializer fromBytes(byte[] bytes) {
...
}
public byte[] toBytes() {
...
}
}
public class Foo<T extends Serializer> {
private T t;
public Foo(T t) {
this.t = t;
}
public void foo() {
t.toBytes(); //this will polymorph into the correct call because it's called on the object instance and not the Serializer class
}
public void bar(byte[] bytes) {
T.fromBytes(bytes); // I'd like to be able to override this method so I can use different implementations
}
}
I'm not sure if this is a good approach, but how about using Jackson library and serialize your object as a json node? for example:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes({
#Type(value = SoundFile.class, name = "sound"),
#Type(value = VideoFile.class, name = "video")
})
abstract class File{
private String id;
private String type;
#JsonCreator
public File(#JsonProperty("id") String id)
{
this.id=id;
}
public String getId() {return this.id;}
public abstract String getType();
}
class SoundFile extends File{
#JsonCreator
public SoundFile(#JsonProperty("id") String id) {
super(id);
}
#Override
public String getType() {
return "sound";
}
}
class VideoFile extends File{
#JsonCreator
public VideoFile(#JsonProperty("id") String id) {
super(id);
}
#Override
public String getType() {
return "video";
}
}
public class GenericApp {
public static void main(String[] args) {
ObjectMapper om = new ObjectMapper();
List<File> files = Arrays.asList(new VideoFile("1"),new SoundFile("2"));
//serialize
List<byte[]> fileSerialized = files.stream().map(file->{
try {
return om.writeValueAsBytes(file);
}catch(Exception e) {return null;}
}).collect(Collectors.toList());
//de-serialize
List<File> filesDeSerialized = fileSerialized.stream().map(bytes ->{
try {
return om.readValue(bytes, File.class);
}
catch(Exception e) {return null;}
}).collect(Collectors.toList());
filesDeSerialized.stream().forEach(file->{
System.out.println("id :"+file.getId()+" - "+file.getClass());
});
}
}
this would properly deserialize these objects and print:
id :1 - class com.dsncode.stackoverflow.VideoFile
id :2 - class com.dsncode.stackoverflow.SoundFile
however, you should define a #JsonTypeInfo and a #JsonSubType for all your sub-classes of your Generic Type. Because, by indicating this field, you will indicate to Jackson deserializer, which class should create for your generic type.
I have an Entity class with a set of enums:
#Entity
public class Something {
public enum Type{
FIRST_ENUM((short)1),
SECOND_ENUM((short)2);
private short id;
private Type(short id) {
this.id = id;
}
public short getId() {
return id;
}
}
#CollectionTable(name="table_name", joinColumns=#JoinColumn(name="something_id"))
#Column(name="type")
private Set<Type> types;
... //other props + getters and setters
}
For the enum I made a converter (whole converter package is loaded by #EntityScan annotation) :
#Converter(autoApply=true)
public class TypeConverter implements AttributeConverter<Type, Integer> {
#Override
public Integer convertToDatabaseColumn(Type st) {
//implementation
}
#Override
public Type convertToEntityAttribute(Integer i) {
//implementation
}
}
Now when I try to use the enum in a query
... AND {packagename}.Something$Type.FIRST_ENUM MEMBER OF {someobject}.something.types ...
I stumble upon following error:
org.hibernate.QueryException: Unrecognized Hibernate Type for handling query constant ({package}.Something$Type.FIRST_ENUM); expecting LiteralType implementation or AttributeConverter
Does anyone got a clue why I cannot use the enum in my query? It somehow seems the enum is not known to Hibernate. I don't understand why, because the class is loaded when I start my application.
I would like all my objects to have an ID and I wish to serialise it for some child class but not for some others
for example:
public class A {
protected Long id;
..getter and setter
}
public class B extends A {
#Override
#JsonIgnore
public Long getId() {..}
#Override
#JsonIgnore
public void setId(Long id) {..}
}
public class C extends B {
#Override
#JsonInclude
public Long getId() {..}
#Override
#JsonInclude
public void setId(Long id) {..}
}
public class Test {
Set<C> tests ...
..getter setter
}
I have tried serialising Test but the JSON string doesn't include the IDs
If I remove the JsonIgnore from B then in that case the Ids are there.
Is there a way with jackson to archive this?
Use
#JsonIgnore(false)
instead of
#JsonInclude
I'm trying to deserialize JSON Array, which is persisted into my MongoDB, to a Java object by using Jackson. I found many tutorials mentioned to handle this polymorphism by adding:
#JsonTypeInfo(use=Id.CLASS,property="_class")
to a Super-class. However, in my case, I can't be able to modify the Super-class. So, are there some solutions to solve it without modifying the Super-class? Here is my code:
public class User {
#JsonProperty("_id")
private String id;
private List<Identity> identities; // <-- My List contains objects of an abstract class; Identity
public User(){
identities = new ArrayList<Identity>();
}
public static Iterable<User> findAllUsers(){
return users().find().as(User.class); // Always give me the errors
}
/*More code*/
}
It always give me the error - Can not construct instance of securesocial.core.Identity, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information.
You can use #JsonDeserilize annotation to bind a concrete implementation class to an abstract class. If you cannot modify your abstract class you can use the Jackson Mix-in annotations to tell Jackson how to find the implementation class.
Here is an example:
public class JacksonAbstract {
public static class User {
private final String id;
private final List<Identity> identities;
#JsonCreator
public User(#JsonProperty("_id") String id, #JsonProperty("identities") List<Identity> identities) {
this.id = id;
this.identities = identities;
}
#JsonProperty("_id")
public String getId() {
return id;
}
public List<Identity> getIdentities() {
return identities;
}
}
public static abstract class Identity {
public abstract String getField();
}
#JsonDeserialize(as = IdentityImpl.class)
public static abstract class IdentityMixIn {
}
public static class IdentityImpl extends Identity {
private final String field;
public IdentityImpl(#JsonProperty("field") String field) {
this.field = field;
}
#Override
public String getField() {
return field;
}
}
public static void main(String[] args) throws IOException {
User u = new User("myId", Collections.<Identity>singletonList(new IdentityImpl("myField")));
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Identity.class, IdentityMixIn.class);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(u);
System.out.println(json);
System.out.println(mapper.readValue(json, User.class));
}
}
I would like to marshall a Collection as nested attributes.
Right now I have:
#XmlElement(name="entry")
public Collection<Integer> getSizes(){ ... }
which returns:
<entry>1</entry>
<entry>2</entry>
But I would like to get:
<entry id="1"/>
<entry id="2"/>
Is this possible without new classes?
Seems to be impossible without new classes at all. Use XmlAdapter:
class EntryAdapter extends XmlAdapter<EntryAdapter.Entry, Integer>
{
public EntryAdapter.Entry marshal(Integer id) {
return new Entry(id);
}
public Integer unmarshal(Entry e) {
return e.getId();
}
static class Entry
{
private Integer id;
public Entry() {}
public Entry(Integer id) { this.id = id; }
#XmlAttribute
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
}
}
-
#XmlElement(name="entry")
#XmlJavaTypeAdapter(EntryAdapter.class)
public Collection<Integer> getSizes(){ ... }
As the accepted answer says, XmlAdapter is the standard JAXB solution.
But if you are using EclipseLink MOXy as your JAXB provider and can use one of its extensions, namely #XmlPath, it can be used to achieve the same result.
To marshal the collection values as attributes, you use it like this:
#XmlPath("entry/#id")
public Collection<Integer> getSizes(){ ... }