'interface' is a reserved word in Java, making it a poor choice for an XML element name.
However, the existing code was using the 'interface' naming, and it was necessary to develop in accordance with the same 'interface' naming to maintain backward compatibility.
Therefore, I first attached the
@XmlElement
annotation to the field to be bound, specifying the name as 'interface' like below.
In attempting to find 'interface' within _beanProperties, no result appears, leading to the prop becoming null.
Consequently, an error occurs in handleUnknownVanilla with
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "interface"
.
Another solution to this problem is utilizing the _caseInsensitive attribute found in _beanProperties.
By adding the configuration
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
, it becomes possible to find in _beanProperties without distinguishing between uppercase and lowercase, thereby finding the properties correctly.
Additionally, using
@JacksonXmlProperty
instead of
@XmlElement
results in 'interface' being registered in _beanProperties, making it discoverable.
import
javax.xml.bind.annotation.XmlElement
;
import
javax.xml.bind.annotation.XmlRootElement
;
import
com.fasterxml.jackson.annotation.JsonMerge
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.dataformat.xml.XmlMapper
;
import
com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlCData
;
import
com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper
;
import
com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty
;
import
com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement
;
public
class
ListTest
{
public
static
void
main
(
String
[]
args
)
throws
JsonProcessingException
{
String
xml
=
""
+
"<Data>"
+
" <product>a</product>"
+
" <product>b</product>"
+
" <backUrl>www.naver.com</backUrl>"
+
" <product>c</product>"
+
" <product>d</product>"
+
" <backUrl>www.naver.com</backUrl>"
+
" <product>e</product>"
+
"</Data>"
;
XmlMapper
m
=
new
XmlMapper
();
// m.setDefaultMergeable(true);
Data
data
=
m
.
readValue
(
xml
,
Data
.
class
);
System
.
out
.
println
(
data
.
getProduct
());
@JacksonXmlRootElement
(
localName
=
"data"
)
class
Data
{
@JacksonXmlCData
@JacksonXmlElementWrapper
(
useWrapping
=
false
)
@JacksonXmlProperty
private
List
<
String
>
product
;
@JacksonXmlCData
@JacksonXmlElementWrapper
(
useWrapping
=
false
)
@JacksonXmlProperty
private
String
backUrl
;
public
List
<
String
>
getProduct
()
{
return
product
;
public
void
setProduct
(
List
<
String
>
product
)
{
this
.
product
=
product
;
public
String
getBackUrl
()
{
return
backUrl
;
public
void
setBackUrl
(
String
backUrl
)
{
this
.
backUrl
=
backUrl
;
Multiple 'product' tags are supposed to be bound to a List object, but when actually calling getProduct, only 'e' appears. Although the XML request format was not standard, proper List object binding occurred with the older
jaxb-api(2.1)
, necessitating a solution for this issue within
jackson-dataformat-xml
as well.
The first thing we can do is modify the setProduct method as follows. Changing it to add the product instead of overwriting it will yield the desired result.
public
void
setProduct
(
List
<
String
>
product
)
{
if
(
this
.
product
==
null
)
{
this
.
product
=
product
;
}
else
{
this
.
product
.
addAll
(
product
);
Another method exists as well. From
jackson-dataformat-xml(2.9)
onwards, you can use the provided setDefaultMergeable.
Result without setDefaultMergeable true setting: [e]
Result with setDefaultMergeable true setting: [a, b, c, d, e]
However, there's one point of caution when using setDefaultMergeable. If the getter for the product is implemented as below to defend against null, then since the initial this.product is null, the result of the getProduct method becomes EMPTY_LIST.
public
List
<
String
>
getProduct
()
{
return
Objects
.
isNull
(
this
.
product
)
?
Collections
.
emptyList
()
:
Collections
.
unmodifiableList
(
this
.
product
);
Internally, when merging, the getProduct method is called, but since it initially receives EMPTY_LIST as a result, addition doesn't occur. This leads to an error:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: (was java.lang.UnsupportedOperationException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.UnsupportedOperationException)
, even when using
@JsonMerge
.
Therefore, either implement getProduct in its basic form or
public
List
<
String
>
getProduct
()
{
if
(
this
.
product
==
null
)
{
this
.
product
=
new
ArrayList
<>();
return
this
.
product
;
Built on
Forem
— the
open source
software that powers
DEV
and other inclusive communities.
Made with love and
Ruby on Rails
. DEV Community
©
2016 - 2024.