- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在使用 RetroFit 和 Jackson 的 REST API。在以下情况下基于搜索查询检索用户时考虑以下响应 JSON:
找到一个结果
{
name: "API name",
results: {
count: 1
users: {
username: "username",
age: 15
}
}
}
找到多个结果
{
name: "API name",
results: {
count: 2,
users: [{
username: "username1",
age: 18
}, {
username: "username2",
age: 19
}]
}
}
如您所见,users-property 包含动态 JSON:根据找到的结果,“users”的值可以是用户对象列表,也可以是 1 个用户对象。
因此,我使用多态设计了我的 Java POJO,如下所示:
public class UserResponse {
@JsonProperty("name")
private String apiName
@JsonProperty("results")
private AResultList resultList
//Getters & Setters
//Constructor
@JsonCreator
public UserResponse(@JsonProperty("name") String name, @JsonProperty("results") AResultList r) {
this.apiName = name;
this.resultList = r;
}
}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "classType"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = ResultObject.class, name="ResultObject"),
@JsonSubTypes.Type(value = ResultList.class, name="ResultList")
})
public abstract class AResultList {
@JsonProperty("count)
private long totalCount;
//Getters & Setters
//Constructors
@JsonCreator
public AResultList(@JsonProperty("count) long count) {
this.totalCount = count;
}
}
public class ResultObject extends AResultList {
@JsonProperty("users")
private User user;
//Getters & Setters
//Constructor
@JsonCreator
public ResultObject(@JsonProperty("count) long count, @JsonProperty("users") User u) {
super(count);
this.user = u;
}
}
public class ResultList extends AResultList {
@JsonProperty("users")
private List<User> users;
//Getters & Setters
//Constructor
@JsonCreator
public ResultObject(@JsonProperty("count) long count, @JsonProperty("users") List<User> u) {
super(count);
this.users = u;
}
}
public class User {
@JsonProperty("username")
private String username;
@JsonProperty("age")
private long userAge;
//Getters & Setters
//Constructor
@JsonCreator
public User(@JsonProperty("username") String u, @JsonProperty("age") long a) {
this.userAge = a;
this.username = u;
}
}
供您引用:用于实例化 RetroFit 的 fragment
ObjectMapper o = new ObjectMapper();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(JacksonConverterFactory.create(o))
.client(okClient)
.build();
然而,尝试检索此信息会导致以下错误:
com.fasterxml.jackson.databind.JsonMappingException: Could not find creator property with name 'count' (in class org.namespace.AResultList)
at [Source: java.io.InputStreamReader@41cd2648; line: 1, column: 1]
我已经被这个“动态数据”问题困住了 2 天了。已经尝试使用 GSON 库和许多其他东西但无济于事。所以想问一下:
- 为什么 jackson 会造成这种情况?这是一个错误吗?一些用户已经问过这个问题,但提供的解决方案不适用于我的情况。
- 这是处理动态数据的正确方法吗?
我已经在不使用多态类(并且只从 API 中检索 1 个用户)和对象映射的情况下完美地测试了我的代码。问题是由多态性引起的,但我不知道如何解决它。
最佳答案
您在 Jackson 注释中指定的多态性配置建议 {"classType":"ResultObject",...}
或 {"classType":"ResultList",...}
将在 JSON 中——但事实并非如此。我不确定您收到的错误的确切原因,但它似乎正在寻找抽象类的创建者,因为没有类型属性。
[对于多态性,Jackson 需要从 JSON 中读取一些内容以确定此时要反序列化的 bean 类型:您实际上没有,只有 users
的数组/对象。因此我认为 Jackson 的多态性支持不适合这种情况]
事实上,要允许属性获取单个项目或项目列表,您只需启用 ACCEPT_SINGLE_VALUE_AS_ARRAY
反序列化功能。但是,这需要全局启用,似乎没有办法将其定位到特定属性。
public static final class UserResponse {
public String name;
public Results results;
public static final class Results {
public int count;
public List<User> users;
}
public static final class User {
public String username;
public int age;
}
}
@Test
public void reads_single_result() throws Exception {
ObjectReader reader = new ObjectMapper().reader(UserResponse.class)
.with(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.with(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES).with(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
UserResponse response = reader.readValue("{ name: 'API name', results: { count: 1,"
+ " users: { username: 'username', age: 15 } } }");
assertThat(response.results.users, iterableWithSize(1));
assertThat(response.results.users.get(0).username, equalTo("username"));
}
@Test
public void reads_two_results() throws Exception {
ObjectReader reader = new ObjectMapper().reader(UserResponse.class)
.with(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.with(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES).with(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
UserResponse response = reader.readValue("{ name: 'API name', results: { count: 2,"
+ " users: [{ username: 'username1', age: 18 }, { username: 'username2', age: 19 }] } }");
assertThat(response.results.users, iterableWithSize(2));
assertThat(response.results.users.get(0).username, equalTo("username1"));
assertThat(response.results.users.get(1).username, equalTo("username2"));
}
哦,如果你想摆脱其中无用的结果对象,你可以使用转换器来实现:
public static final class UserResponseWithConverter {
public String name;
@JsonProperty("results")
@JsonDeserialize(converter = ConvertResultsToUserList.class)
public List<User> users;
public static final class Results {
public int count;
public List<User> users;
}
public static final class User {
public String username;
public int age;
}
public static final class ConvertResultsToUserList extends StdConverter<Results, List<User>> {
@Override
public List<User> convert(Results value) {
return value.users;
}
}
}
配置正确的序列化作为练习留给读者 ;)
关于java - Retrofit 2.0,Jackson 和多态性 : Could not find creator property with name <. ..>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33069401/
我来自 Asp.Net 世界,试图理解 Angular State 的含义。 什么是 Angular 状态?它类似于Asp.Net中的ascx组件吗?是子页面吗?它类似于工作流程状态吗? 我听到很多人
我一直在寻找 3 态拨动开关,但运气不佳。 基本上我需要一个具有以下状态的开关: |开 |不适用 |关 | slider 默认从中间开始,一旦用户向左或向右滑动,就无法回到N/A(未回答)状态。 有人
我是一名优秀的程序员,十分优秀!