2

设想

  • 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 响应中返回

问题

如果在实体中将属性 Z 设置为 @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

4 回答 4

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 时,您将不得不使用自定义的基于视图的ObjectWriters 序列化它们:

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

然后,如果你这样做basicObjectWriter.writeValueAsString(responseObject),它将只写Xand YfullObjectWriter.writeValueAsString(responseObject)会写X,YZ.

于 2013-09-19T18:33:53.060 回答
0

BeanSerializerModifier为此,您可以尝试使用 Jackson's 。为了动态排除属性,您需要适当地扩展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如下(使用 a 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

这个问题ObjectMapper涉及在Jersey中使用自定义 Jackson 代码(以 的形式)。

希望这可以帮助!

于 2013-09-19T18:33:18.000 回答
0

如果不需要发送 null 值,可以将不想发送的变量设置为 null,并设置 Jackson 忽略 null 属性。这样,在 request1 上,您可以将 Z 设置为 null。另一种方法是使用扩展来模拟你的类,但我不知道杰克逊是否可以在这种情况下轻松解析。

于 2013-09-19T19:00:32.883 回答
0

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

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

  • 选择您想在通话时看到的字段
  • 在单个调用中导航实体关系以获取复杂视图
于 2013-09-19T21:19:26.930 回答