gpt4 book ai didi

java - Jackson JSON、不可变类和接口(interface)

转载 作者:太空狗 更新时间:2023-10-29 22:40:05 24 4
gpt4 key购买 nike

我正在使用 Jackson 示例,但在使用不可变类和接口(interface)进行反序列化时遇到了一些问题。

下面是我的代码:

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):

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 无法解析 Address,它是 AddressImpl 的接口(interface),而 AddressImpl 是一个具体的实现。我一直在浏览文档并查看了一些关于 @JsonDeserialize(as=AddressImpl.class) 的文章,但它没有用。所以我很难过。有没有人让这个工作,甚至支持吗?

如果我在 UserImpl 类中将 Address 替换为 AddressImpl,它会像冠军一样工作。

最佳答案

以防万一你没有看到它,这是一个blog entry讨论使用不可变对象(immutable对象)和 Jackson。

但您绝对应该能够使用 @JsonDeserialize(as=AddressImpl.class); 将其添加到 Address.java 接口(interface)(直接或使用混合插件),或通过将其添加到字段或属性。需要注意的一件事是,对于反序列化,它必须在您使用的访问器旁边; setter ,如果你有一个,如果没有,在字段旁边。注解还没有(还)在访问者之间共享;因此,例如将它添加到“ setter/getter ”是行不通的。

Jackson 1.8 最终还允许注册从抽象到具体的类型(有关更多详细信息,请参阅 http://jira.codehaus.org/browse/JACKSON-464),这可能是指示“AddressImpl”用于“地址”的最佳选择。

关于java - Jackson JSON、不可变类和接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6345325/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com