How to ignore as well as property editing for JSON

2019-06-19 10:54发布

As part of my requirement I am exposing a web service which takes a Employee class as input in JSON format. Employee class as follows. If you see there are 3 properties inside the Class like status, password, creationTime. Now I am trying to stop user from giving properties such as status and creationTime. I mean to say I dont want to allow user to input the JSON as:-

{
  "emp_id": "xyz@gmail.com",
  "credentials" : {"password": "xxxxx"},
  "status": "ACTIVE",
  "creationTime": "<UTC time>"
}

When status and creationTime are entered it should result in 400 error message. Similarly when I display the result back to user something like return Response.status(Status.ACCEPTED).entity(employee).build(); it should not display creationTime or credentials. it should look like :-

 {
      "emp_id": "xyz@gmail.com",
      "status": "ACTIVE",
    }

I could see that there is a @JsonIgnore property which is not working in my case for status. I tried jackson.

My Employee class is as follows:

import java.util.Date;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;

@XmlRootElement
public class Employee {
    @XmlElement(name = "emp_id", required = true)
    @JsonProperty("emp_id")
    private String empId;
    private Credentials credentials;
    private String status;
    private Date creationTime;

    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

    public Credentials getCredentials() {
        return credentials;
    }

    public void setCredentials(Credentials credentials) {
        this.credentials = credentials;
    }

    @JsonIgnore
    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Date getCreationTime() {
        return creationTime;
    }

    public void setCreationTime(Date creationTime) {
        this.creationTime = creationTime;
    }

}

标签: java rest
4条回答
Deceive 欺骗
2楼-- · 2019-06-19 11:09

First of all, check what is the Json/XML parser you are using. Jersey defaults to Moxy, so replace Moxy with Jackson as @JsonIgnore you are using is Jackson annotation.

Add the below dependencies to enable Jackson parser for both Json and XML.

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.5.4</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-xml-provider</artifactId>
    <version>2.5.4</version>
</dependency>

Jersey has the auto discovery mechanism that should register Jackson automatically, if that failed, use the below class.

public class ResourceConfig extends org.glassfish.jersey.server.ResourceConfig {

    public ResourceConfig() {
    super();
    registerJacksonProvider();
    packages("com.rest");
    }

    /**
     * Custom provider to handle JSON and XML request
     */
    private void registerJacksonProvider() {
    ObjectMapper mapper = new ObjectMapper();
    XmlMapper xmlMapper = new XmlMapper();

    xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
    mapper.enable(SerializationFeature.INDENT_OUTPUT);

    JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
    JacksonJaxbXMLProvider xmlProvider = new JacksonJaxbXMLProvider();

    provider.setMapper(mapper);
    xmlProvider.setMapper(xmlMapper);

    register(provider);
    register(xmlProvider);
    }

}

To disable Moxy, add the below class.

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;

import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.server.ServerProperties;

@Provider
public class DisableMoxyFeature implements Feature {
    @Override
    public boolean configure(final FeatureContext context) {
    final String disableMoxy = CommonProperties.MOXY_JSON_FEATURE_DISABLE + '.'
        + context.getConfiguration().getRuntimeType().name().toLowerCase();
    context.property(disableMoxy, true);
    context.property(CommonProperties.MOXY_JSON_FEATURE_DISABLE, true);
    context.property(ServerProperties.MOXY_JSON_FEATURE_DISABLE, true);
    return true;
    }
}
查看更多
我命由我不由天
3楼-- · 2019-06-19 11:13

Jersey default JSON provider

From Jersey documentation:

JSON binding support via MOXy is a default and preferred way of supporting JSON binding in your Jersey applications since Jersey 2.0. When JSON MOXy module is on the classpath, Jersey will automatically discover the module and seamlessly enable JSON binding support via MOXy in your applications.

Since MOXy supports JAXB annotations, try using @XmlTransient. It should do the trick.

Using Jackson as JSON provider

To use Jackson 2.x as your JSON provider you need to add jersey-media-json-jackson module to your pom.xml file:

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

To use Jackson 1.x you'll need the jersey-media-json-jackson1 module:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson1</artifactId>
    <version>2.22.1</version>
</dependency>

For more information about the dependencies, have a look at Jersey documentation.

If you can, choose Jackson 2.x over Jackson 1.x.

Registering Jackson as JSON provider

In order to use Jackson as your JSON provider you need to register JacksonFeature for Jackson 2.x (or Jackson1Feature for Jackson 1.x) in your ResourceConfig class (Jersey's own implementation of Application class):

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(JacksonFeature.class);
    }
}

For more details, have a look at the documentation.

Choosing the correct JsonProperty annotation

Ensure you are using the correct JsonProperty annotation according to Jackson version:

For more details about the annotations, have a look at the documentation:

Try annotating your field

Additionally, instead of annotating the getStatus() method, try annotating the status field with the proper @JsonProperty annotation.

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-06-19 11:22

While building the json response object from employee object using JSON-Lib, you can pass on a jsonconfig which can exclude specific properties or you can also set a json property filter to that config like below

JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
  public boolean apply(Object source, String name, Object value) {
    if ("credentials".equals(name) || "creationTime".equals(name)) {
      return true;
    }
    return false;
  }
});

OR

JsonConfig config = new JsonConfig();
List<String> excludes = new ArrayList<String>();
excludes.add("credentials");
excludes.add("creationTime");

JSONObject.fromObject(response, jsonConfig);

For the first part of your question, you can very well use json schema and validate the received json object before processing

JSONSchemaValidator.validate(jsonBody, <path_of_your_schema_file>);
JSONObject jsonObj = JSONObject.fromObject(jsonBody);
查看更多
SAY GOODBYE
5楼-- · 2019-06-19 11:35

whenever your rest web service will recent this json object, it will convert it to POJO object. If your JSON object doesn't contain some fields which are there in POJO object, then those values will be initialized to NULL.

Now you can give 404 response accordingly by checking the null values.

查看更多
登录 后发表回答