期望一个对象数组,但得到一个对象中的一个对象
Expected an array of objects but got an object in an object
在我目前正在进行的项目中,我遇到了一个 angular 异常:Error: [$resource:badcfg] Error in resource configuration. Expected response to contain an array but got an object?
在寻找解决方案的过程中,我直接在浏览器中输入了 Web 服务的 URL,令人惊讶的是我没有收到预期的数组。
Web 服务 class:
@Path("/menu")
public class MenuHandler {
@GET
@Path("/cls")
@Produces(MediaType.APPLICATION_JSON)
public List<Clazz> getCLSs() {
Clazz clazz = new Clazz();
Clazz.setFoo("foo");
Clazz.setBar("bar");
ArrayList<Clazz> clazzes = new ArrayList<>();
clazzes.add(clazz);
return clazzes;
}
}
当我输入 url http://localhost:8080/myProject/rest/menu/cls
时,我希望看到一个包含 JSON 个对象的 JSON 数组:
[ {"foo": "foo", "bar": "bar"} ]
但是,我收到了一个 JSON 对象,其中包含 属性 我期望的 JSON 对象没有任何数组:
{
"clazz": {
"foo": "foo",
"bar": "bar"
}
}
所以我想知道为什么没有数组,当我添加另一个 Clazz 对象时会发生什么。在那种情况下,我仍然得到一个 JSON 对象,但这次其中一个参数是我希望从一开始就拥有的 JSON 数组。
{
"clazz": [
{
"foo": "foo",
"bar": "bar"
},
{
"foo": "foo2",
"bar": "bar2"
}
]
}
谁能解释一下为什么会出现这种行为以及我的想法哪里出了问题?
您可能想使用 GenericEntity 和 return Response。
@GET
@Path("/cls")
@Produces({ MediaType.APPLICATION_JSON })
public Response getCLSs() {
List<Clazz> objects = new ArrayList<Clazz>();
// logic goes here
// now wrap List into GenericEntity
GenericEntity<List<Clazz>> entity = new GenericEntity<List<Clazz>>(
objects) {
};
return Response.ok(entity).build();
}
所以我发现了问题。我能够重现它。看来你只是忘了启用 POJOMappingFeature
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
这使用 Jackson 来 deserialize/serialize。如果未设置,它将使用 Jersey 的内部 JSON 提供程序到 deserialize/serialize。我不确定如何配置默认提供程序,但我认为还是使用 Jackson 更安全。
另外,在我上面的评论中,我说要测试是否使用了 Jackson。轻松完成此操作的一种方法是仅创建一个 ContextResolver
和一个 s.o.p。在 getContext
方法中。当需要映射器时调用此方法。所以如果使用 Jackson,s.o.p 应该打印
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper defaultMapper;
public ObjectMapperContextResolver() {
defaultMapper = new ObjectMapper();
}
@Override
public ObjectMapper getContext(Class<?> type) {
System.out.println("--- getContext ---");
return defaultMapper;
}
}
请注意,这也是使用 Jackson serization/deserialization 进行任何配置的一种方法(只需配置映射器)。
在我目前正在进行的项目中,我遇到了一个 angular 异常:Error: [$resource:badcfg] Error in resource configuration. Expected response to contain an array but got an object?
在寻找解决方案的过程中,我直接在浏览器中输入了 Web 服务的 URL,令人惊讶的是我没有收到预期的数组。
Web 服务 class:
@Path("/menu")
public class MenuHandler {
@GET
@Path("/cls")
@Produces(MediaType.APPLICATION_JSON)
public List<Clazz> getCLSs() {
Clazz clazz = new Clazz();
Clazz.setFoo("foo");
Clazz.setBar("bar");
ArrayList<Clazz> clazzes = new ArrayList<>();
clazzes.add(clazz);
return clazzes;
}
}
当我输入 url http://localhost:8080/myProject/rest/menu/cls
时,我希望看到一个包含 JSON 个对象的 JSON 数组:
[ {"foo": "foo", "bar": "bar"} ]
但是,我收到了一个 JSON 对象,其中包含 属性 我期望的 JSON 对象没有任何数组:
{
"clazz": {
"foo": "foo",
"bar": "bar"
}
}
所以我想知道为什么没有数组,当我添加另一个 Clazz 对象时会发生什么。在那种情况下,我仍然得到一个 JSON 对象,但这次其中一个参数是我希望从一开始就拥有的 JSON 数组。
{
"clazz": [
{
"foo": "foo",
"bar": "bar"
},
{
"foo": "foo2",
"bar": "bar2"
}
]
}
谁能解释一下为什么会出现这种行为以及我的想法哪里出了问题?
您可能想使用 GenericEntity 和 return Response。
@GET
@Path("/cls")
@Produces({ MediaType.APPLICATION_JSON })
public Response getCLSs() {
List<Clazz> objects = new ArrayList<Clazz>();
// logic goes here
// now wrap List into GenericEntity
GenericEntity<List<Clazz>> entity = new GenericEntity<List<Clazz>>(
objects) {
};
return Response.ok(entity).build();
}
所以我发现了问题。我能够重现它。看来你只是忘了启用 POJOMappingFeature
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
这使用 Jackson 来 deserialize/serialize。如果未设置,它将使用 Jersey 的内部 JSON 提供程序到 deserialize/serialize。我不确定如何配置默认提供程序,但我认为还是使用 Jackson 更安全。
另外,在我上面的评论中,我说要测试是否使用了 Jackson。轻松完成此操作的一种方法是仅创建一个 ContextResolver
和一个 s.o.p。在 getContext
方法中。当需要映射器时调用此方法。所以如果使用 Jackson,s.o.p 应该打印
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
private final ObjectMapper defaultMapper;
public ObjectMapperContextResolver() {
defaultMapper = new ObjectMapper();
}
@Override
public ObjectMapper getContext(Class<?> type) {
System.out.println("--- getContext ---");
return defaultMapper;
}
}
请注意,这也是使用 Jackson serization/deserialization 进行任何配置的一种方法(只需配置映射器)。