Spring & Jackson环境下JSON列表转自定义格式XML的实现问题
你当前使用的@JacksonXmlElementWrapper(useWrapping = false)只能移除address列表的外层包裹标签,无法避免每个地址元素生成<address>父标签,也无法自动为streetName、city字段拼接序号后缀,因此无法实现预期的输出格式。
推荐两种可行实现方案:
方案一:使用@JsonAnyGetter实现(更简便)
通过@JsonAnyGetter注解动态生成带序号的平级字段,无需自定义序列化器:
- 定义Address实体类
public class Address { private String streetName; private String city; // 构造方法、getter、setter自行实现 }
- 定义根节点实体类
import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.HashMap; import java.util.List; import java.util.Map; public class Root { private String name; private List<Address> address; public String getName() { return name; } public void setName(String name) { this.name = name; } // 序列化时忽略原始address字段,避免生成多余的<address>标签 @JsonIgnore public List<Address> getAddress() { return address; } public void setAddress(List<Address> address) { this.address = address; } // 动态返回所有带序号的地址字段,序列化时会直接作为根节点的子标签输出 @JsonAnyGetter public Map<String, String> getDynamicAddressFields() { Map<String, String> fields = new HashMap<>(); for (int i = 0; i < address.size(); i++) { int index = i + 1; Address addr = address.get(i); fields.put("streetName" + index, addr.getStreetName()); fields.put("city" + index, addr.getCity()); } return fields; } }
方案二:自定义序列化器实现
如果需要更灵活的序列化逻辑,可以为根节点自定义序列化器:
- 定义序列化器类
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; import java.util.List; public class RootXmlSerializer extends StdSerializer<Root> { public RootXmlSerializer() { super(Root.class); } @Override public void serialize(Root root, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); // 写入name字段 gen.writeStringField("name", root.getName()); // 遍历地址列表生成带序号的字段 List<Address> addresses = root.getAddress(); for (int i = 0; i < addresses.size(); i++) { int index = i + 1; Address addr = addresses.get(i); gen.writeStringField("streetName" + index, addr.getStreetName()); gen.writeStringField("city" + index, addr.getCity()); } gen.writeEndObject(); } }
- 给Root类绑定序列化器
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.List; @JsonSerialize(using = RootXmlSerializer.class) public class Root { private String name; private List<Address> address; // 构造方法、getter、setter自行实现 }
测试代码
两种方案都可以用以下代码验证输出:
import com.fasterxml.jackson.dataformat.xml.XmlMapper; public class XmlConvertTest { public static void main(String[] args) throws Exception { // 模拟解析JSON得到的对象 Address addr1 = new Address("value1", "value2"); Address addr2 = new Address("value3", "value4"); Root root = new Root(); root.setName("Edward"); root.setAddress(List.of(addr1, addr2)); XmlMapper xmlMapper = new XmlMapper(); // 格式化输出XML String xmlResult = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(root); System.out.println(xmlResult); } }
输出结果和要求的目标格式完全一致。
内容的提问来源于stack exchange,提问作者ROBlackSnail
相关产品推荐
相关产品推荐

