Estoy jugando con los ejemplos de Jackson y estoy teniendo algunos problemas para lograr que la deserialización funcione con clases e interfaces inmutables.Jackson JSON, clases inmutables e interfaces
A continuación es mi código:
package com.art.starter.jackson_starter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
/** * Hello world! * */ public class App {
public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException
{
System.out.println("Hello World!");
AddressImpl.AddressBuilder builder = new AddressImpl.AddressBuilder();
NameImpl.Builder nameBuilder = new NameImpl.Builder();
UserImpl.Builder userBuilder = new UserImpl.Builder();
Name name = nameBuilder.first("FirstName")
.last("LastName")
.build();
Address address = builder.setCity("TestCity")
.setCountry("TestCountry")
.setState("PA")
.setStreet("TestAddress")
.setZip(123)
.build();
User user = userBuilder.address(address)
.gender(User.Gender.MALE)
.isVerified(true)
.userImage(new byte[5])
.build();
System.out.println(address);
System.out.println(name);
System.out.println(user);
StringWriter sw = new StringWriter();
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(sw, user);
System.out.println(sw);
StringReader sr = new StringReader("{\"address\":{\"state\":\"PA\",\"country\":\"TestCountry\",\"street\":\"TestAddress\",\"city\":\"TestCity\",\"zip\":123},\"verified\":true,\"gender\":\"MALE\",\"userImage\":\"AAAAAAA=\"}");
/*
This line throws the Exception
*/
User user2 = mapper.readValue(sr, UserImpl.class);
System.out.println(user2);
} }
package com.art.starter.jackson_starter;
import java.util.Arrays;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
public final class UserImpl implements User
{
private final Address address;
private final Gender gender;
private final byte[] userImage;
private final boolean isVerified;
public static class Builder
{
private Address address;
private Gender gender;
// private Name name;
private byte[] userImage;
private boolean isVerified;
public Builder address(Address address)
{
this.address = address;
return this;
}
public Builder gender(Gender gender)
{
this.gender = gender;
return this;
}
// public Builder name(Name name)
// {
// this.name = name;
// return this;
// }
public Builder userImage(byte[] userImage)
{
this.userImage = userImage;
return this;
}
public Builder isVerified(boolean isVerified)
{
this.isVerified = isVerified;
return this;
}
public UserImpl build()
{
return new UserImpl(address, gender, userImage, isVerified);
}
}
@JsonCreator
public UserImpl(@JsonProperty("address") Address address, @JsonProperty("gender") Gender gender, @JsonProperty("userImage") byte[] userImage,
@JsonProperty("verified") boolean isVerified)
{
super();
this.address = address;
this.gender = gender;
this.userImage = userImage;
this.isVerified = isVerified;
}
public Address getAddress()
{
return address;
}
public Gender getGender()
{
return gender;
}
public byte[] getUserImage()
{
return userImage;
}
public boolean isVerified()
{
return isVerified;
}
@Override
public String toString()
{
StringBuilder builder2 = new StringBuilder();
builder2.append("UserImpl [address=");
builder2.append(address);
builder2.append(", gender=");
builder2.append(gender);
builder2.append(", isVerified=");
builder2.append(isVerified);
builder2.append(", name=");
builder2.append(", userImage=");
builder2.append(Arrays.toString(userImage));
builder2.append("]");
return builder2.toString();
}
}
package com.art.starter.jackson_starter;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
public final class AddressImpl implements Address
{
private final String city;
private final String country;
private final String street;
private final String state;
private final int zip;
public static class AddressBuilder
{
private String city;
private String country;
private String street;
private String state;
private int zip;
public AddressBuilder setCity(String city)
{
this.city = city;
return this;
}
public AddressBuilder setCountry(String country)
{
this.country = country;
return this;
}
public AddressBuilder setStreet(String street)
{
this.street = street;
return this;
}
public AddressBuilder setState(String state)
{
this.state = state;
return this;
}
public AddressBuilder setZip(int zip)
{
this.zip = zip;
return this;
}
public AddressImpl build()
{
return new AddressImpl(city, country, street, state, zip);
}
}
@JsonCreator
public AddressImpl(@JsonProperty("city") String city, @JsonProperty("country") String country, @JsonProperty("street") String street,
@JsonProperty("state") String state, @JsonProperty("zip") int zip)
{
this.city = city;
this.country = country;
this.street = street;
this.state = state;
this.zip = zip;
}
public String getCity()
{
return city;
}
public String getCountry()
{
return country;
}
public String getStreet()
{
return street;
}
public String getState()
{
return state;
}
public int getZip()
{
return zip;
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("AddressImpl [city=");
builder.append(city);
builder.append(", country=");
builder.append(country);
builder.append(", state=");
builder.append(state);
builder.append(", street=");
builder.append(street);
builder.append(", zip=");
builder.append(zip);
builder.append("]");
return builder.toString();
}
}
El problema parece ser con la Dirección. Tengo esta excepción:
Exception in thread "main" org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.art.starter.jackson_starter.Address, problem: abstract types can only be instantiated with additional type information
at [Source: [email protected]; line: 1, column: 2]
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
at org.codehaus.jackson.map.deser.StdDeserializationContext.instantiationException(StdDeserializationContext.java:212)
at org.codehaus.jackson.map.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:97)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:230)
at org.codehaus.jackson.map.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:595)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:472)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:350)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2391)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1614)
at com.art.starter.jackson_starter.App.main(App.java:56)
Estoy seguro que esto se debe a que no hay manera de Jackson a resolver la dirección, que es una interfaz para AddressImpl que es una aplicación concreta. He estado hurgando en los documentos y he consultado algunos artículos sobre @JsonDeserialize (as = AddressImpl.class), pero no funcionó. Así que estoy perplejo. ¿Alguien alguna vez ha conseguido que esto funcione, incluso es compatible?
Funciona como un campeón si reemplazo Address
con AddressImpl
en la clase UserImpl
.
¿cuál es exactamente la línea 56? Ayudaría a saber exactamente qué código arroja el Ex –
@ Aaron-lo siento, editó la edición - está en la penúltima línea del vacío estático principal – nsfyn55
Tuve un problema similar, este recurso podría ayudar: http: //wiki.fasterxml. com/JacksonPolymorphicDeserialization – will824