Jackson XML序列化非基本类型为属性报错Trying to write an attribute求解
解决方案
问题根源
Jackson XML序列化时,对于自定义类、集合这类非简单类型,即使标注了isAttribute = true,默认也会按照复杂对象逻辑生成嵌套子元素;如果自定义序列化器错误调用了writeStartObject等生成结构化内容的方法,就会抛出属性写入时无开放起始元素的异常。
具体修改步骤
1. 新增Rectangle类型转换器
和你已有的ListConverter逻辑一致,把Rectangle对象转为符合格式要求的字符串:
public class BoundsConverter extends StdConverter<Rectangle, String> { @Override public String convert(Rectangle bounds) { if (bounds == null) { return ""; } int x2 = bounds.x + bounds.width; int y2 = bounds.y + bounds.height; return String.format("[%d,%d][%d,%d]", bounds.x, bounds.y, x2, y2); } }
2. 修正实体类注解
给两个非简单类型字段的@JsonSerialize注解补充as = String.class,明确告诉Jackson序列化后输出为字符串类型,避免按复杂对象处理:
@JacksonXmlProperty(localName = "tags", isAttribute = true) @JsonDeserialize(using = ListDeserializer.class) // 明确序列化后为字符串类型 @JsonSerialize(converter = ListConverter.class, as = String.class) private List<String> tags; @JacksonXmlProperty(localName = "bounds", isAttribute = true) @JsonDeserialize(using = BoundsDeserializer.class) // 用新增的BoundsConverter做转换,明确输出为字符串 @JsonSerialize(converter = BoundsConverter.class, as = String.class) private Rectangle bounds;
3. 可选:XmlMapper配置优化
如果使用Jackson 2.13及以上版本,推荐用builder模式初始化XmlMapper,避免旧版本默认配置的兼容问题:
XmlMapper mapper = XmlMapper.builder() .enable(SerializationFeature.INDENT_OUTPUT) // 禁止空标签自动转为null,避免反序列化异常 .disable(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL) .build();
自定义序列化器的正确写法(如果不用Converter的场景)
如果你想改用自定义Serializer而不是Converter,注意不要调用任何生成结构化节点的方法,直接输出字符串即可:
public class BoundsSerializer extends JsonSerializer<Rectangle> { @Override public void serialize(Rectangle value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value == null) { gen.writeNull(); return; } int x2 = value.x + value.width; int y2 = value.y + value.height; String boundsStr = String.format("[%d,%d][%d,%d]", value.x, value.y, x2, y2); // 直接写字符串,不要调用writeStartObject等方法 gen.writeString(boundsStr); } }
实体类对应修改为:
@JacksonXmlProperty(localName = "bounds", isAttribute = true) @JsonDeserialize(using = BoundsDeserializer.class) @JsonSerialize(using = BoundsSerializer.class) private Rectangle bounds;
内容的提问来源于stack exchange,提问作者AweSIM
相关产品推荐
相关产品推荐

