使用双向 JACKSON

Working with bi-dirctional JACKSON

首先,抱歉我的英语不好;

其次,我有以下代码:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")    

public class UserAccount implements Serializable  {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private List<Venda> vendas;

    }

以及以下内容:

public class Venda implements Serializable  {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private UserAccount cliente;

    }

So, everything is okay and get the json from serialize on this way (when I ask for an UserAccount):

[
  {
    "id": 1,    
    "vendas": [
      {
        "id": 1,        
        "cliente": 1,        
      }
    ]
  }
]

And when I ask for a Venda:

[
  {
    "id": 1,    
    "cliente": {
      "id": 1,      
      "vendas": [
        {
          "id": 1,        
          "cliente": 1         
        }
      ]
    }
  }
]

问题是,在第一种情况下,我不需要 "vendas" 的 "cliente" 信息,但在第二种情况下,我需要 "cliente" 信息,但是我不需要我想要他的 "vendas",因为我之前已经拿到了;

我已经试过 @JsonIgnore 但对我不起作用,我该怎么办?

PS:我正在使用 GSON 从 JSON 获取 .Class,但我得到了一个可怕的异常,因为有时 cliente 是对象,有时是整数,所以如果你们有另一种解决方案可以让客户和供应商不改变他们的类型,我也想知道。 :(

我能够使用 Jackson 的 Mix-in feature. The Mixin feature is a class were you can specify json annotations (on the class, fields and getters/setters) and they apply to the bean/pojo you serialize. Basically, a mixin allows adding annotations at run time and without chaning the bean/pojo source file. You use Jackson's module feature 在 运行 应用 Mixin 来解决这个问题。

所以我创建了一个动态添加 @JsonIgnore 注释到 UserAccount class 的 vendas getter 方法的 mixin,以及另一个添加 @JsonIgnore 注释的 mixin Venda class 的客户 getter 方法。

这里是修改后的UserAccountclass:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class UserAccount implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private List<Venda> vendas = new ArrayList<>();

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public List<Venda> getVendas() { return vendas; }
    public void        setVendas(List<Venda> vendas) { this.vendas = vendas; }
    public void        addVenda(Venda v) { 
        this.vendas.add(v);
        v.setCliente(this);
    }

    /**
     * a Jackson module that is also a Jackson mixin 
     * it adds @JsonIgnore annotation to getVendas() method of UserAccount class
     */
    public static class FilterVendas extends SimpleModule {
        @Override
        public void setupModule(SetupContext context) {
            context.setMixInAnnotations(UserAccount.class, FilterVendas.class);
        }
        // implementation of method is irrelevant. 
        // all we want is the annotation and method's signature 
        @JsonIgnore
        public List<Venda> getVendas() { return null; }  
    }

这里是修改后的Vendaclass:

public class Venda implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private UserAccount cliente;

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public UserAccount getCliente() { return cliente; }
    public void        setCliente(UserAccount cliente) { this.cliente = cliente; }

    /**
     * a Jackson module that is also a Jackson mixin 
     * it adds @JsonIgnore annotation to getCliente() method of Venda class
     */
    public static class FilterCliente extends SimpleModule {
        @Override
        public void setupModule(SetupContext context) {
            context.setMixInAnnotations(Venda.class, FilterCliente.class);
        }
        // implementation of method is irrelevant. 
        // all we want is the annotation and method's signature 
        @JsonIgnore
        public UserAccount getCliente() { return null; }
    }
}

以及具有 运行 时间对象映射器配置的测试方法:

public static void main(String... args) {
    Venda v = new Venda();
    UserAccount ua = new UserAccount();
    v.setId(1L);
    ua.setId(1L);
    ua.addVenda(v);
    try {
        ObjectMapper mapper = new ObjectMapper();
        System.out.println("UserAccount: (unfiltered)");
        System.out.println(mapper.writeValueAsString(ua));

        mapper = new ObjectMapper();
        // register module at run time to apply filter
        mapper.registerModule(new Venda.FilterCliente());
        System.out.println("UserAccount: (filtered)");
        System.out.println(mapper.writeValueAsString(ua));

        mapper = new ObjectMapper();
        System.out.println("Venda: (unfiltered)");
        System.out.println(mapper.writeValueAsString(v));

        mapper = new ObjectMapper();
        // register module at run time to apply filter
        mapper.registerModule(new UserAccount.FilterVendas());
        System.out.println("Venda: (filtered)");
        System.out.println(mapper.writeValueAsString(ua));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出:

UserAccount: (unfiltered)
{"id":1,"vendas":[{"id":1,"cliente":1}]}
UserAccount: (filtered)
{"id":1,"vendas":[{"id":1}]}
Venda: (unfiltered)
{"id":1,"cliente":{"id":1,"vendas":[{"id":1,"cliente":1}]}}
Venda: (filtered)
{"id":1}

谢谢大家,我是这样解决的:

public class CustomClienteSerializer extends JsonSerializer<UserAccount> {

@Override
public void serialize(UserAccount cliente, JsonGenerator generator, SerializerProvider provider)
        throws IOException, JsonProcessingException {

    cliente.setVendas(null);
    generator.writeObject(cliente);

}

}

并将其添加到我的 venda class:

@JsonSerialize(using = CustomClienteSerializer.class)   
@ManyToOne(fetch = FetchType.EAGER)
private UserAccount cliente;

所以...我得到了我想要的json!