Java JSON RESTful Web服务 - 过滤字段

时间:2013-09-19 13:13:56

标签: java json rest jackson

方案

  • Jersey / JacksonJson我的RESTful Web服务请求。
  • 具有属性X,Y,Z的实体A.
  • 2个RESTful请求。
  • 请求1应返回JSON响应中具有属性X,Y的实体A
  • 请求2应返回JSON响应中具有属性X,Y,Z的实体A
  • 实体A的配置使得属性Z使用@JsonIgnore,因此不会在JSON响应中返回

问题

如果在实体中设置为@JsonIgnore,如何在请求2中返回属性Z?除了使用@JsonIgnore之外,还有更好的方法吗? 下面是一些“演示”代码,以帮助澄清我的问题。

@Entity
Class A implements Serializable {
  String X;
  String Y;
  String Z;

  @JsonIgnore
  public String getZ() {
    return Z;
  }
}

@Path("form")
Class Request {
    @GET
    @Path("request1")
    @Produces({"application/json"})
    public A request1() {
      return A;
    }

    @GET
    @Path("request2")
    @Produces({"application/json"})
    public A request2() {
      return A;
    }
}

4 个答案:

答案 0 :(得分:2)

您可以使用@JsonView注释。

类似的东西:

public class Views {
    public static class BasicView {
    }

    public static class FullView extends BasicView {
    }
}

然后在班级A

  @JsonView(Views.BasicView.class)
  public String getX() {
    return X;
  }


  @JsonView(Views.BasicView.class)
  public String getY() {
    return Y;
  }


  @JsonView(Views.FullView.class)
  public String getZ() {
    return Z;
  }

当您必须返回JSON时,您必须使用基于自定义视图的ObjectWriter序列化它们:

public static final ObjectWriter basicObjectWriter = objectMapper
            .writerWithView(Views.BasicView.class);
public static final ObjectWriter fullObjectWriter = objectMapper
            .writerWithView(Views.FullView.class);

然后,如果您执行basicObjectWriter.writeValueAsString(responseObject),则只会写入XYfullObjectWriter.writeValueAsString(responseObject)会写XYZ

答案 1 :(得分:0)

您可以尝试使用杰克逊的BeanSerializerModifier来达到此目的。为了动态排除属性,您需要扩展BeanSerializerModifier并适当地实现changeProperties方法。以下代码段适用于相关示例:

public class CustomBeanSerializerModifier extends BeanSerializerModifier
{
    private String path;

    public CustomBeanSerializerModifier(String path)
    {
        this.path = path;
    }

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
            BeanDescription desc, List<BeanPropertyWriter> inputProperties)
    {
        List<BeanPropertyWriter> outputProperties = new ArrayList<>();
        for (BeanPropertyWriter property : inputProperties) {
            if (path.startsWith("request1") && property.getType().getRawClass().equals(A.class)) {
                if (property.getName().equals("Z")) {
                    continue;
                }
            }
            outputProperties.add(property);
        }
        return super.changeProperties(config, desc, outputProperties);
    }
}

将此插入杰克逊的ObjectMapper,如下所示(使用Module):

public class CustomModule extends Module
{
    private String path;

    public CustomModule(String path)
    {
        this.path = path;
    }

    @Override
    public void setupModule(SetupContext context)
    {
        context.addBeanSerializerModifier(new CustomBeanSerializerModifier(path));
    }

    // Other overridden methods
}

ObjectMapper objectMapper = new ObjectMapper();
String path = getJerseyPath();
CustomModule module = new CustomModule(path);
objectMapper.registerModule(module);

// Call objectMapper.writeValue() to serialize stuff

This question涉及在泽西岛使用自定义杰克逊代码(以ObjectMapper的形式)。

希望这有帮助!

答案 2 :(得分:0)

如果您不需要发送空值,则可以将不希望发送的变量设置为null,并将Jackson设置为忽略null属性。这样,在request1上,您可以将Z设置为null。 其他方法是使用extend来模拟你的classe,但我不知道Jackson是否可以在这种情况下轻松解析。

答案 3 :(得分:0)

你说你正在使用Jersey / JAX-RS,所以你Yoga应该特别感兴趣。

  

Yoga扩展了JAX-RS和SpringMVC RESTful服务器,以提供GData和LinkedIn风格的字段选择器。

     
      
  • 选择您希望在通话时看到的字段
  •   
  • 在复合视图的单个调用中导航实体关系
  •