我有一個 Java 類,我想對 XML 進行序列化/反序列化。此類的每個屬性都應序列化/反序列化為 XML 元素的屬性/從 XML 元素的屬性進行序列化/反序列化。
XML 看起來像:
<element fullName="Asim" age="30" score="0.78" readonly="true" bounds="[0,0][10,20]" tags="tag1,tag2,tag3">
...
...
</element>
如果屬性很簡單 ( String, int, boolean),則此方法有效。我可以簡單地使用@JacksonXmlProperty注釋并完成作業:
@JacksonXmlProperty(localName = "fullName", isAttribute = true)
private String fullName;
但是,某些屬性是我需要在序列化/反序列化期間轉換的類物件 ( bounds, list)。我已經能夠使用@JsonDeserialize注釋來讀取 XML:
@JacksonXmlProperty(localName = "bounds", isAttribute = true)
@JsonDeserialize(using = BoundsDeserializer.class)
private Rectangle bounds;
另一方面,將這些領域序列化被證明是一個相當大的挑戰。我已經嘗試使用JsonSerialize(using = BoundsSerializer.class)和JsonSerialize(converter = BoundsConverter.class)并沒有什么作品。要么我得到以下例外:
com.fasterxml.jackson.core.JsonGenerationException: Trying to write an attribute when there is no open start element.
或者生成的 XML 看起來像:
<element fullName="Asim" age="30" score="0.78" readonly="true">
<bounds>
<x>0</x>
<y>0</y>
<width>10</width>
<height>20</width>
</bounds>
<tags tags="tag1" tags="tag2" tags="tag3" />
...
...
</element>
如何將類的非原始屬性序列化為 XML 中的字串屬性?
編輯
主要呼叫代碼:
try {
XmlMapper mapper = new XmlMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
String xml = mapper.writeValueAsString(this);
return xml;
}
catch (Exception ex) { ... }
要序列化/反序列化的類的相關位:注釋行是我嘗試(但失敗)的替代方法。
@JacksonXmlRootElement(localName = "root")
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@EqualsAndHashCode
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Slf4j
public class XML {
@JacksonXmlProperty(localName = "text", isAttribute = true)
private String text;
@JacksonXmlProperty(localName = "tags", isAttribute = true)
@JsonDeserialize(using = ListDeserializer.class)
@JsonSerialize(converter = ListConverter.class)
//@JsonSerialize(using = ListSerializer.class)
//@JsonUnwrapped
private List<String> tags;
@JacksonXmlProperty(localName = "bounds", isAttribute = true)
@JsonDeserialize(using = BoundsDeserializer.class)
//@JsonSerialize(using = BoundsSerializer.class, contentAs = String.class)
private Rectangle bounds;
}
邊界解串器:
public class BoundsDeserializer extends JsonDeserializer<Rectangle> {
private static final Pattern BOUNDS_PATTERN = Pattern.compile("\\[(-?\\d ),(-?\\d )]\\[(-?\\d ),(-?\\d )]");
@Override
@Nullable
public Rectangle deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getValueAsString();
if (value.isBlank()) {
return null;
}
Matcher m = BOUNDS_PATTERN.matcher(value);
if (!m.matches()) {
return ctxt.reportInputMismatch(Rectangle.class, "Not a valid bounds string: '%s'", value);
}
final int x1 = Integer.parseInt(m.group(1));
final int y1 = Integer.parseInt(m.group(2));
final int x2 = Integer.parseInt(m.group(3));
final int y2 = Integer.parseInt(m.group(4));
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
}
串列反序列化器:
public class ListDeserializer extends JsonDeserializer<List<String>> {
@Override
@Nullable
public List<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getValueAsString();
if (value.isBlank()) {
return null;
}
String deBracketed = value.trim().replaceAll("^\\[(.*)]$", "$1");
List<String> listValues = Arrays.stream(deBracketed.split(","))
.map(String::trim)
.filter(Predicate.not(String::isEmpty))
.collect(Collectors.toUnmodifiableList());
return listValues;
}
}
串列轉換器:
public class ListConverter extends StdConverter<List<String>, String> {
@Override
public String convert(List<String> list) {
return String.join(",", list);
}
}
謝謝!阿西姆
uj5u.com熱心網友回復:
所以我解決這個問題的方法如下:
@JacksonXmlProperty(localName = "tags", isAttribute = true)
@JsonDeserialize(using = ListDeserializer.class)
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private List<String> tags;
@JacksonXmlProperty(localName = "tags", isAttribute = true)
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private String tagsAsString() {
return String.join(",", this.tags);
}
第一個欄位是只寫的,所以它只會被反序列化。第二個欄位是只讀的,所以它只會被序列化。然而,這感覺真的很hackish,我認為必須有比這更好的解決方案。:/
uj5u.com熱心網友回復:
我想出了一個更好的方法來做同樣的事情:
// Used during serialization
@JacksonXmlProperty(localName = "bounds", isAttribute = true)
@JsonSerialize(converter = RectangleToStringConverter.class)
// Used during deserialization
@JsonProperty("bounds")
@JsonDeserialize(converter = StringToRectangleConverter.class)
private Rectangle bounds;
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/336696.html
上一篇:比較十六進制字串和雙精度
