【问题标题】:JSONObject as a member variable in POJO not recognized -JerseyJSONObject 作为 POJO 中的成员变量无法识别 -Jersey
【发布时间】:2016-01-01 18:25:39
【问题描述】:

我正在构建一个 RESTful Web 服务。我被锁定在无法继续进行的情况下。我有一个 DAO(一个 POJO),它有一个 JSONObject 作为成员变量。当我尝试从客户端(邮递员或用户定义的 javascript)进行 POST 调用并尝试调试时,JSONObject 的 getter 中收集的值是空的({}),而该类的其他成员获得了他们的适当价值观。我尝试用@XmlElement@JsonProperty 等注释JSONObject 及其吸气剂。没有任何效果。

类看起来像:

package org.somepackage

import javax.xml.bind.annotation.XmlRootElement;

    import org.codehaus.jackson.annotate.JsonAutoDetect;
    import org.codehaus.jackson.annotate.JsonProperty;
    import org.json.JSONObject;


    @XmlRootElement

    public class someClass {
        private String someID;
        private String someName;

        private JSONObject someJsonObject;


        public someClass () {

        }
        public someClass (String id, String name,
                JSONObject jsonObj) {
            someID=id;
            someName=name;
            someJsonObject=jsonObj;

        }
        public String getSomeID() {
            return someID;
        }
        public void setSomeID(String id) {
            this.SomeID= id;
        }
        public String getSomeName() {
            return someName;
        }
        public void setSomeName(String name) {
            this.someName= name;
        }

        public JSONObject getSomeJsonObject() {
            return someJsonObject;
        }
        public void setSomeJsonObject(JSONObject jsonObj) {
            this.someJsonObject= jsonObj;
        }
    }

感谢您的帮助! 谢谢。


编辑

示例 JSON

{ 
  "name": "ABCD", 
  "ID": "P63784433", 
  "theJSON":{
    "string":"foo",
    "number":5,
    "array":[1,2,3],
    "object":{
      "property":"value‌​",
      "subobj":{
        "arr":["foo","ha"],
        "numero":1
      }
    }
  }
}

依赖 web.xml 对 Jackson 的依赖

                        <dependency>
                                <groupId>org.codehaus.jackson</groupId>
                                <artifactId>jackson-mapper-asl</artifactId>
                                <version>1.9.2</version>
                        </dependency>

                        <dependency>
                                <groupId>org.codehaus.jackson</groupId>
                                <artifactId>jackson-core-asl</artifactId>
                                <version>1.9.2</version>
                        </dependency>

                         <dependency>
                                <groupId>org.codehaus.jackson</groupId>
                                <artifactId>jackson-jaxrs</artifactId>
                                <version>1.9.2</version>
                         </dependency>

                         <dependency>
                                <groupId>org.codehaus.jackson</groupId>
                                <artifactId>jackson-xc</artifactId>
                                <version>1.9.2</version>
                        </dependency>

                        <dependency>
                                <groupId>com.fasterxml.jackson.core</groupId>
                                <artifactId>jackson-core</artifactId>
                                <version>2.6.2</version>
                        </dependency>

通过 web.xml 注册资源和提供者

    <!-- Register JAX-RS Application -->
   <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>my.package.MyApplication</param-value>
    </init-param>

    <!-- Register resources and providers under my.package. -->
   <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>my.package</param-value>
    </init-param>

    <!-- Register custom provider  -->
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>my.package.mapper.ObjectMapperProvider</param-value>
    </init-param>`

MyApplication.java

`@ApplicationPath("/")
public class MyApplication extends ResourceConfig {

public MyApplication() {
    // Register resources and providers using package-scanning.
    packages("my.package");

    register(ObjectMapperProvider.class);


}`

【问题讨论】:

  • 创建另一个嵌套 POJO 类来表示 JSONObject 中的数据,否则对于任意数据格式,只需使用 Map 而不是 JSONObject
  • 谢谢@peeskillet,我听从了你的建议,但没有运气。无论其内容是什么,该对象仍被解析为空的JSONObject。你知道是否有其他方法可以解决这个问题?我需要使用JSON 的信息,可以使用Map 吗?
  • 共享您通过 POST API 传递的正文和标头
  • @peeskillet! JSON 结构如下所示:{ "name": "ABCD", "ID": "P63784433", "theJSON":{"string":"foo","number":5,"array":[1,2,3],"object":{"property":"value","subobj":{"arr":["foo","ha"],"numero":1}}} }
  • @kyle ,正文是我在此评论上方发布的内容。同样关于标题,我发回了这种形式的回复:Response.ok(someString,MediaType.APPLICATION_JSON).status(201).header(CorsHeaderConstants.HEADER_AC_ALLOW_METHODS,"GET POST DELETE PUT").header(CorsHeaderConstants.HEADER_AC_ALLOW_CREDENTIALS,"true").header(CorsHeaderConstants.HEADER_AC_ALLOW_ORIGIN,"*").header(CorsHeaderConstants.HEADER_AC_ALLOW_ORIGIN,"*").allow("OPTIONS").build(); 我想提一下,我的 POST API 一直在为其他类型的 POJO 工作,我只使用包含 JSONObject 的那个!

标签: java json jersey jackson jsonobject


【解决方案1】:

问题在于 Jackson 不知道如何创建 JSONObject(至少在没有帮助的情况下并非如此)。 Jackson 主要处理基本类型和 POJO。如果您希望能够处理JSONObject(假设这是来自org.json 的对象),您可以添加jackson-datatype-json-org 以获得Jackson 支持。

下面是一个完整的测试。这是我用来测试的依赖项

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20141113</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.16</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-json-org</artifactId>
  <version>2.3.2</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>2.16</version>
    <scope>test</scope>
</dependency>

注意:我用于jackson-datatype-json-org 的Jackson 版本与jersey-media-json-jackson 2.16 使用的Jackson 版本相同。如果您使用的是该球衣 jackson 的不同版本,则需要确保它引入的 Jackson 版本与您使用的 jackson-datatype-json-org 版本相同。这样我们就不会混合 Jackson 版本。

这是使用Jersey Test Framework的测试

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.json.JSONObject;

import org.junit.Test;
import static junit.framework.Assert.*;

/**
 *
 * @author Paul Samsotha
 */
public class JsonOrgTest extends JerseyTest {

    public static class Model {
        public String firstName;
        public String lastName;
        public JSONObject other;
        // should br private with correct getters and setters
    }

    @Path("model")
    public static class ModelResource {

        @POST
        @Consumes(MediaType.APPLICATION_JSON)
        @Produces(MediaType.APPLICATION_JSON)
        public Response post(Model model) {
            return Response.ok(model).build();
        }
    }

    @Provider
    public static class ObjectMapperProvider implements ContextResolver<ObjectMapper> {

        private final ObjectMapper mapper;

        public ObjectMapperProvider() {
            mapper = new ObjectMapper();
            mapper.registerModule(new JsonOrgModule());
        }

        @Override
        public ObjectMapper getContext(Class<?> type) {
            return mapper;
        }
    }

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(ModelResource.class)
                .register(ObjectMapperProvider.class)
                .register(JacksonFeature.class);
    }

    @Override
    public void configureClient(ClientConfig config) {
        config.register(JacksonFeature.class);
        config.register(ObjectMapperProvider.class);
    }

    @Test
    public void should_return_org_json_data() {
        final String json 
                = "{\n"
                + "  \"firstName\": \"pee\",\n"
                + "  \"lastName\": \"skillet\",\n"
                + "  \"other\": {\n"
                + "    \"age\": 100,\n"
                + "    \"birthday\": \"yesterday\"\n"
                + "  }\n"
                + "}";
        Response response = target("model").request().post(Entity.json(json));
        if (response.getStatus() != 200) {
            System.out.println(response.getStatus() + ": " + response.readEntity(String.class));
            fail("should return data and 200");
        } else {
            Model model = response.readEntity(Model.class);
            JSONObject other = model.other;
            System.out.println(other.toString());
            assertEquals("pee", model.firstName);
            assertEquals("skillet", model.lastName);
            assertEquals(100, other.getInt("age"));
            assertEquals("yesterday", other.getString("birthday"));
        }
    }
}

您还应该做的是摆脱所有您在上面评论中的 Jackson 依赖项。 Jackson JSON 支持只需要一个依赖项。

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.16</version>
</dependency>

还要注意测试中的ObjectMapperProvider。您需要使用ObjectMapper 注册JsonOrgModule,以便Jackson 能够处理JSONObject。这个很重要。如果你没有ContextResolver,上面的例子就会失败。

【讨论】:

  • 非常感谢。根据您的建议,我添加了ObjectMapperProvider 类,用于将JsonOrgModule 注册为ObjectMapper。如何将其与someClass 链接?
  • @vardhinisuresh27 你不需要链接任何东西。只要注册了ObjectMapperProvider,它就应该可以工作,如我完整的可运行/可测试示例中所示
  • 谢谢。但我从你的测试代码中看到configure() 函数注册了ObjectMapperProvider。那么在我的情况下,我该怎么做呢?
  • 我不知道,你还没有展示你的案例。我不知道您如何注册所有资源类和提供者。你在使用包裹扫描吗?如果是这样,扫描应该选择@Provider注解并为您注册,只要该类在列出的要扫描的包或子包中。
  • 另外请记住,您应该摆脱帖子中的所有 Jackson 依赖项。只需使用我的答案中的那个
猜你喜欢
  • 2017-04-07
  • 1970-01-01
  • 1970-01-01
  • 2021-01-06
  • 2021-02-27
  • 2013-05-15
  • 2018-11-12
  • 1970-01-01
相关资源
最近更新 更多