如何基于Lombok @Builder与Jackson @JsonProperty实现含动态数量递增键名重复对象的模型序列化
Great question! Having to manually define fields like object1, object2, etc., gets messy fast—especially if you need to support a variable number of these objects. Here are a couple of clean, maintainable solutions that eliminate code duplication while producing the exact JSON structure you need.
Solution 1: Use a Map<String, RandomObject> (Simplest Approach)
Instead of hardcoding individual fields, use a Map where the keys follow the objectN pattern. Jackson will automatically serialize the Map's keys as top-level JSON properties, which matches your required output perfectly.
Implementation Code
import com.fasterxml.jackson.annotation.JsonAnyGetter; import lombok.Builder; import lombok.Singular; import java.util.LinkedHashMap; import java.util.Map; @Builder public class Sample { // Use Singular to easily add items one by one via the builder @Singular("object") private final Map<String, RandomObject> objects = new LinkedHashMap<>(); // Optional: Enforce the "objectN" key format when adding items public static class SampleBuilder { public SampleBuilder object(int index, RandomObject obj) { if (objects == null) { objects = new LinkedHashMap<>(); } objects.put("object" + index, obj); return this; } } // Jackson uses this to serialize the Map as top-level properties @JsonAnyGetter public Map<String, RandomObject> getObjects() { return objects; } }
How to Use the Builder
// Build your request with dynamic number of objects Sample sample = Sample.builder() .object(1, new RandomObject("random", true)) .object(2, new RandomObject("random", false)) .object(3, new RandomObject("random", true)) .build();
Why This Works
LinkedHashMappreserves the order of your objects (soobject1comes beforeobject2, etc.).@JsonAnyGettertells Jackson to treat each Map entry as a top-level JSON property instead of nesting them under anobjectskey.- Lombok's
@Singularlets you add objects one by one without manually managing the Map.
Solution 2: Use a List<RandomObject> with Custom Serialization
If you prefer working with a List (e.g., for easier iteration or collection operations), you can create a custom Jackson serializer to convert the List into the numbered key structure.
Step 1: Define the Model Class
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Builder; import lombok.Singular; import java.util.List; @Builder @JsonSerialize(using = SampleSerializer.class) public class Sample { @Singular("object") private final List<RandomObject> objects; // Getter needed for the serializer to access the list public List<RandomObject> getObjects() { return objects; } }
Step 2: Create the Custom Serializer
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; public class SampleSerializer extends JsonSerializer<Sample> { @Override public void serialize(Sample sample, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartObject(); if (sample.getObjects() != null) { for (int i = 0; i < sample.getObjects().size(); i++) { // Generate "object1", "object2", etc. as keys gen.writeObjectField("object" + (i + 1), sample.getObjects().get(i)); } } gen.writeEndObject(); } }
How to Use the Builder
Sample sample = Sample.builder() .object(new RandomObject("random", true)) .object(new RandomObject("random", false)) .object(new RandomObject("random", true)) .build();
Pros of This Approach
- Uses a
List, which is more intuitive for managing a collection of identical objects. - Full control over the serialization logic (e.g., you could add validation for the number of objects if needed).
Bonus: Adding Deserialization Support (If Needed)
If you also need to parse JSON with these numbered keys back into your model, you can create a custom JsonDeserializer that reads all keys starting with object and maps them to either a Map or List. For example, a deserializer for the List approach would iterate over all JSON properties, filter for objectN keys, sort them, and populate the List.
内容的提问来源于stack exchange,提问作者Ip Man

