Collaborating with two-way JACKSON communication channels

Apologies for my poor English;

Below is the code snippet in question:

@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;

    }

And here's another snippet:

public class Venda implements Serializable  {

    private static final long serialVersionUID = 1L;

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

    private UserAccount cliente;

    }

When serializing an UserAccount object, the JSON output is as follows:

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

On the other hand, when serializing a Venda object:

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

The issue arises where I do not want the "cliente" information nested under "vendas" in the first case, but in the second case, I need the "cliente" information without its associated "vendas". How can I achieve this without using @JsonIgnore?

Furthermore, when deserializing with GSON, I encounter exceptions due to inconsistent types of "cliente" (Object and Integer). Is there a solution that maintains the type consistency of "cliente" and "vendas"? Any suggestions are appreciated.

Answer №1

By utilizing Jackson's Mix-in feature, I successfully managed to solve this problem. This particular feature allows you to specify JSON annotations on classes, fields, and getter/setter methods which are then applied to the bean or POJO you serialize. Essentially, a mix-in enables the addition of annotations at runtime without the need to modify the source file of the bean/POJO. To implement this, Jackson's module feature is used to apply a Mixin dynamically during runtime.

In my approach, I created one mix-in that adds the @JsonIgnore annotation to the 'getVendas' getter method of the 'UserAccount' class, and another mix-in that applies the @JsonIgnore annotation to the 'cliente' getter method of the 'Venda' class.

Below is the updated 'UserAccount' class:

@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);
    }

    // FilterVendas - Jackson mixin adding @JsonIgnore to 'getVendas' method
    public static class FilterVendas extends SimpleModule {
        @Override
        public void setupModule(SetupContext context) {
            context.setMixInAnnotations(UserAccount.class, FilterVendas.class);
        }

        @JsonIgnore
        public List<Venda> getVendas() { return null; }  
    }

Here is the modified 'Venda' class:

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; }

    // FilterCliente - Jackson mixin adding @JsonIgnore to 'getCliente' method
    public static class FilterCliente extends SimpleModule {
        @Override
        public void setupModule(SetupContext context) {
            context.setMixInAnnotations(Venda.class, FilterCliente.class);
        }

        @JsonIgnore
        public UserAccount getCliente() { return null; }
    }
}

Finally, here is the test method with runtime object mapper configuration:

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();
        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();
        mapper.registerModule(new UserAccount.FilterVendas());
        System.out.println("Venda: (filtered)");
        System.out.println(mapper.writeValueAsString(ua));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Output:

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}

Answer №2

Appreciation for the help, I managed to find the solution using this approach:

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);

}

}

Furthermore, I made a modification in my venda class by including the following:

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

This adjustment resulted in achieving the desired JSON output!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on incorporating labels to vertices within GRAPHSON, a JSON dependent format designed for graph components

Exploring the link, I am seeking guidance on how to label vertices in a JSON file to optimize graph traversals. My current setup includes using Titan graph DB, where GRAPHSON conversion and Gremlin query language are utilized. To enhance vertex retrieval s ...

A guide to dynamically extracting values from JSON objects using JavaScript

I have a JSON array with a key that changes dynamically (room number varies each time I run the code). My goal is to access the inner JSON array using this dynamic key. Here's what I've attempted so far, but it's throwing an error. Here is ...

Statistics Sweden SCB API call was made, but unfortunately, no data was retrieved

I am having trouble accessing the actual values of the data in my table, as all I can see is the dates in the JSON output generated. The specific link I am using is: "http://api.scb.se/OV0104/v1/doris/en/ssd/START/FM/FM5001/FM5001A/FM5001SDDSPM" ...

Converting XML to Json with the help of Json-lib

Currently, I'm working on an Android project where I need to convert an XML document from a web source into JSON format. This is the approach I've taken: URL url; InputStream in; try { url = new URL("http://www.aemet.es/xml/municipios/loca ...

Using Kotlin to work with JSON strings that contain line breaks and variables

In need of help adding linebreakers to a JSON string for improved readability. val myString = "some string" val myObjectJson = ` { "example1": "value", "example2": $myString }` This will allow me to utilize ...

Transforming a JSON file into a new JSON file using an alternative method in React

I have a JSON data structure similar to this example: [ { "quantity": "200", "prodType": "stock", "symbol": "LOL", "prodDesc": "Εθνική τράπεζα", "market": "Greece", "averageCost": "131,16", ...

Validating two unique JSON responses using JSONSchema

Two JSON responses have been successfully validated against a defined schema using the jsonschema library. The responses have different field names but still pass validation. Below is the specified schema query_schema = { "type": "object", "prope ...

The JSON schema is failing to validate the mandatory attribute

I have been working on coding a Json Schema that defines the layout created by the user. Within this schema, I have defined different properties such as "stdAttribute" and "stdItem" with specific types and required attributes. However, when I set certain d ...

Method for transmitting JSON array from Controller to View using CodeIgniter

I have a function in my controller: function retrieveAllExpenses() { $date=$this->frenchToEnglish_date($this->input->post('date')); $id_user=$this->session->userdata('id_user'); $where=array('date&ap ...

Tips for extracting text from a multiline tag using Selenium

I need help extracting the text "1 file has been successfully uploaded" from the code snippet below: <div class="formbuttons"> <h3 id="res" class="demo" style="color: rgb(255, 255, 255); display: block;"> <center>1 file <br>has bee ...

What is the best way to implement my function on every value in a JSON file?

I've got a JSON file that contains the following dataset: [{ "planet": "project pluto", "records": [ { "project": "project pluto", "plan": "paper& ...

Firestore/Javascript error: FirebaseError - The data provided is invalid for the DocumentReference.set() function. An unsupported field value of 'undefined'

I keep encountering this error Error creating user: FirebaseError: Function DocumentReference.set() called with invalid data. Unsupported field value: undefined (found in field diabetesComplication) After some investigation, I realized that the iss ...

Struggling to retrieve data from the HTML Dom? I have already tried using getAttribute() and getText() methods within Selenium WebDriver

I attempted to extract text/value from the Html Dom using getAttribute() and getText() methods in WebDriver, but I wasn't able to retrieve any values in the console. Could someone please assist me in resolving this issue? The image provided does not c ...

What is the best way to send a JSON object array result to my API endpoint in React?

I am currently working on fetching data from 2 different APIs from the backend. The challenge I am facing is that the JSON result I receive from the first API is in the form of an object array in JSON format. My goal is to pass the ID from the first API ...

Is the java.lang.IllegalStateException exception being thrown in the main thread?

I've attempted to download the updated chrome driver and included it in my drivers folder, but I'm still encountering the same error. import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome ...

How to execute an executable file using Java on a Mac computer

Currently, my objective is to launch a server using bash, and I've already crafted an UNIX shell script for this purpose. However, I'm encountering difficulties in executing it through Java within Eclipse. Below is the code snippet that I attemp ...

"Encountered a problem while trying to insert data using JSON and Ajax

I've been struggling to figure out where the issue lies in my code. I've double-checked everything and it all seems correct, but I keep encountering errors. Below is the code snippet: Markup: <link href="http://ajax.googleapis.com/ajax/libs ...

Solving the problem of 'json mime-type on 2003 server

I am currently facing an issue: On a 2003 server with iis 6, I have a functioning solution. However, during every deployment of the solution, I find myself having to manually configure the MIME type on the iis. Although I have implemented this in my web ...

The Restangular library seems to be struggling with handling query parameters

Currently, I am implementing Restangular in my Ionic application and trying to incorporate Infinite scrolling. To achieve this, I need to make a call using Restangular. As I refer to the Restangular documentation (here), I attempted the following approach ...

What is the method for editing individual rows in a data table in Spring MVC when the edit button is clicked?

Every time I click on <a id="myBtn"><i class="fa fa-pencil" style="color:OliveDrab;"></i></a>, I only get a modal on the first row click, and it appears empty. I've searched through many internet resources, but none of them pro ...