I'm building a RESTful web service. I've been locked in a situation where I'm not able to proceed. I've a DAO (a POJO) that has a JSONObject
as a member variable. When I try to make a POST call from client (Postman or user-defined javascript) and try to debug, the value gathered in the getter of the JSONObject
is empty ({}) whereas the other members of the class obtain their appropriate values. I've tried annotating the JSONObject
and its getter with @XmlElement
, @JsonProperty
and so on.. Nothing worked.
The class looks like :
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;
}
}
I appreciate your help! Thanks.
EDIT
Example JSON
{
"name": "ABCD",
"ID": "P63784433",
"theJSON":{
"string":"foo",
"number":5,
"array":[1,2,3],
"object":{
"property":"value",
"subobj":{
"arr":["foo","ha"],
"numero":1
}
}
}
}
DEPENDENCY web.xml dependency on 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>
RESOURCES AND PROVIDER REGISTER through 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);
}`
The problem is that Jackson doesn't know how to create the JSONObject
(at least not without some help). Jackson mainly handle basic type and POJOs. If you want to be able to handle JSONObject
(assuming this is the object from org.json
), you can add the jackson-datatype-json-org
for the Jackson support.
Below is a complete test. Here are the dependencies I used to test
<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>
Note: The Jackson version I am using for jackson-datatype-json-org
is the same Jackson version used by jersey-media-json-jackson
2.16. If you are using a different version of this jersey jackson, you will need to make sure the version of Jackson it pulls in is the same version of jackson-datatype-json-org
you are using. This way we are not mixing Jackson versions.
Here's the test using 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"));
}
}
}
What you should also do is get rid of all the Jackson dependencies you have in your comment above. You only need one dependency for Jackson JSON support.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.16</version>
</dependency>
Also notice the ObjectMapperProvider
in the test. You will need to this to register the JsonOrgModule
with the ObjectMapper
in order for Jackson to be able to handle JSONObject
. This is important. If you don't have the ContextResolver
, the above example will fail.
来源:https://stackoverflow.com/questions/32942810/jsonobject-as-a-member-variable-in-pojo-not-recognized-jersey