SoFunction
Updated on 2025-03-09

Solution to a JSON deserialization problem (empty string becomes empty collection)

1. Problem Scenario

When I define it in the backend entity as follows:

private List<String> projectTypeId;

It is OK if the front-end passes projectTypeId as null or []. If the current terminal passes "" will report an error. The error is reported as follows:

Caused by: : Cannot coerce empty String ("") to element of `<>` (but could if coercion was enabled using `CoercionConfig`)
 at [Source: ($NonClosingInputStream); line: 8, column: 22] (through reference chain: ["projectTypeId"])

It means that the empty string cannot be forced into a collection

2. Solution (front-end)

The front-end just turns "" into null or []

(But the original definition of private String projectTypeId; there is nothing wrong with the front-end transmission of "" but later changes the requirements and needs to be turned into a collection. However, the syntax written by everyone on the front-end is different. If the previous front-end staff is null, they will be passed "" . Therefore, this bug is caused)

3. Solution (backend)

3.1 Write a custom JSON deserializer EmptyStringListDeserializer

package ;

import ;
import ;
import ;
import ;

import ;
import ;
import ;

/**
  * Custom JSON deserializer for handling empty strings in List.
  * This deserializer is designed to be used with the `@JsonDeserialize` annotation in the Java class, which is placed on the List<String> field.
  * @author
  * @date 2023/12/15
  **/
public class EmptyStringListDeserializer extends JsonDeserializer&lt;List&lt;String&gt;&gt; {

    /**
      * Deserialize the JSON array, process the empty string and convert it to an empty list.
      *
      * @param p JSON parser.
      * @param ctxt Deserialization context.
      * @return List<String> containing the deserialized string.
      * @throws IOException If an I/O error occurs during deserialization.
      */
    @Override
    public List&lt;String&gt; deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        // Read the entire JSON node        JsonNode node = ();
        // Check if the node is null, missing or not an array        if (node == null || () || () || !()) {
            // For null, missing or non-array cases, return to empty list            return new ArrayList&lt;&gt;();
        } else {
            // Process each element in the array            List&lt;String&gt; values = new ArrayList&lt;&gt;();
            for (JsonNode element : node) {
                // Check whether the element is a text node                if (()) {
                    // Add text value to the list                    (());
                }
            }
            // Returns the list of deserialized strings            return values;
        }
    }
}

3.2 Then add annotation on entities that may have empty string conversion collections

/**
  * Project type id
  */
@JsonDeserialize(using = )
private List&lt;String&gt; projectTypeId;

@JsonDeserialize

It is during deserialization, so the parameters are encapsulated, so the setXxxx() method is used, so the annotation needs to be added to the corresponding set method. If Lombok is used, you need to define the corresponding set method yourself.

You need to use the using attribute to specify the class that handles parameters. This class needs to inherit the JsonDeserializer class and override deserialize().

Your own opinion:

@JsonDeserialize is a deserialization annotation provided by String. Where using can customize a deserialization, EmptyStringListDeserializer is our custom deserializer for processing the conversion of empty strings into empty sets.

Summarize

This is all about this article about solving a JSON deserialization problem. For more related JSON deserialization problems, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!