如何解决Jackson JSON,不可变的类和接口
| 我正在玩Jackson的示例,并且在进行反序列化以使用不可变的类和接口时遇到一些麻烦。 下面是我的代码: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();
}
}
问题似乎出在地址上。我得到这个例外:
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: java.io.StringReader@785f8172; 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)
我确定这是因为Jackson无法解析地址,而地址是作为具体实现的地址接口的接口。我一直在浏览文档,并查看了有关@JsonDeserialize(as = AddressImpl.class)的几篇文章,但是没有用。所以我很沮丧。有没有人让它起作用,甚至得到了支持吗?
如果我在UserImpl
类中将Address
替换为AddressImpl
,它将像冠军一样工作。
解决方法
以防万一您没有看到它,这是一个博客条目,讨论使用不可变对象和Jackson。
但是通过将ѭ5添加到Address.java接口(直接或通过混合使用),或将其添加到字段或属性,您肯定应该能够使用ѭ5。要注意的一件事是,对于反序列化,它必须在您使用的访问器旁边;如果您在字段旁边有一个,则使用setter。注释尚未(在访问者之间)共享;因此例如将其添加到\'getter \'将不起作用。
杰克逊1.8最终还允许注册从抽象到具体的类型(有关更多详细信息,请参见http://jira.codehaus.org/browse/JACKSON-464),这可能是表明\'AddressImpl \'的最佳选择。用于\'地址\'。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。