我需要使用REST服务提供者提供的XSD文件,使用JAXB自动生成的Java类,来管理REST API激活/返回的json结构。 由于某些原因,我不知道但我必须接受,在最新版本的XSD文件中,ENUM已在具有“值” String属性的复杂类型对象中转换,并且相关的JSON结构使用空,空String来管理这些情况。或包含定义为xsd的可接受值之一的String数组。
所以,现在我有以下xsd片段
<xsd:complexType name='SexType'>
<xsd:sequence>
<xsd:element name='value' minOccurs='1' maxOccurs='1'>
<xsd:simpleType>
<xsd:restriction base='xsd:string'>
<xsd:pattern value='(01|02|98){1}'/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name='YesNoFixedYesType'>
<xsd:sequence>
<xsd:element name='value' minOccurs='1' maxOccurs='1' fixed='1'>
<xsd:simpleType>
<xsd:restriction base='xsd:string'>
<xsd:pattern value='(1|0){1}'/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
...
<xsd:element name = 'sex' minOccurs='1' maxOccurs='1' type='SexType'>
<xsd:element name = 'decision' minOccurs='1' maxOccurs='1' type='YesNoFixedYesType'>
以下JAXB生成的类
根类
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RootClass", propOrder = {
"decision",
"name",
"sex"
})
public class RootClass {
@XmlElement(name = "decision")
protected YesNoFixedYesType decision;
@XmlElement(name = "name")
protected String name;
@XmlElement(name = "sex")
protected SexType sex;
[other properties ]
[getter and setter]
}
(例如)ENUMs类
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "YesNoFixedYesType", propOrder = {
"value"
})
@JsonDeserialize(using=GenericJsonDeserializer.class)
public class YesNoFixedYesType {
@XmlElement(required = true)
protected String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SexType", propOrder = {
"value"
})
@JsonDeserialize(using=GenericJsonDeserializer.class)
public class SexType {
@XmlElement(required = true)
protected String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
还有我必须管理的JSON这样的声音
{
"decision": {
"value": [
"1"
]
},
"name": "test",
"sex": "",
[other properties]
}
如您所见,JSON结构在“ decision”字段中使用String数组,在“ sex”字段中使用简单的空String。
考虑到
我正在尝试使用
这是我的自定义反序列化器(请注意,在我的测试中,即使杰克逊规范说仅使用StdDeserializer,我也尝试扩展StdDeserializer和JsonDeserializer)
package it.ngede.impl.customizations.jackson.legapp;
import .....
public class GenericJsonDeserializer extends StdDeserializer<Object> implements ContextualDeserializer {
private Class<?> targetClass;
public GenericJsonDeserializer() {
super(Object.class);
}
public GenericJsonDeserializer(Class<?> targetClass) {
super(targetClass);
this.targetClass = targetClass;
}
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String sourceValue = "";
try {
//How can I put the right value into "sourceValue" variable?
deserializedObject = targetClass.newInstance();
Method setterMethod = deserializedObject.getClass().getMethod("setValue", String.class);
setterMethod.invoke(deserializedObject, sourceValue);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
//Now I have an instance of the annotated class I can populate the fields via reflection
return deserializedObject;
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException {
//gets the class type of the annotated class
targetClass = ctxt.getContextualType().getRawClass();
//this new JsonApiDeserializer will be cached
return new GenericJsonDeserializer(targetClass);
}
}
现在,我的问题是:如何从json中提取正确的值? 我使用在互联网上找到的所有解决方案执行了许多测试,但没有一个起作用。 有没有人可以帮助我或指出我可以在哪里满足我的需求?
预先感谢
答案 0 :(得分:0)
在我发布问题后几分钟(等了三天在这里写完)之后,我找到了解决方案,我认为遇到同样麻烦的人可能会有所帮助。
这是我的自定义解串器的代码
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
Object deserializedObject = "";
String sourceValue = "";
try {
if (p.getCurrentToken() == JsonToken.START_OBJECT) {
p.nextToken();
if (p.getCurrentToken() == JsonToken.FIELD_NAME && "value".equalsIgnoreCase(p.getCurrentName())) {
System.out.print(p.getCurrentName());
p.nextToken();
if (p.getCurrentToken() == JsonToken.START_ARRAY) {
boolean stillLoop = true;
while(stillLoop) {
switch (p.getCurrentToken()) {
case END_ARRAY:
stillLoop = false;
break;
case VALUE_STRING:
sourceValue = p.getValueAsString();
System.out.println(" = " + sourceValue);
break;
default:
}
p.nextToken();
}
}
}
}
deserializedObject = targetClass.newInstance();
Method getterMethod = deserializedObject.getClass().getMethod("getValue");
if (java.util.List.class.isAssignableFrom(getterMethod.getReturnType())) {
List<String> list = (List<String>) getterMethod.invoke(deserializedObject);
list.add(sourceValue);
} else {
Method setterMethod = deserializedObject.getClass().getMethod("setValue", String.class);
setterMethod.invoke(deserializedObject, sourceValue);
}
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
//Now I have an instance of the annotated class I can populate the fields via reflection
return deserializedObject;
}