我正试图使用flexjson来反序列化从web调用中获得的字符串。问题是其中的一些元素在属性/键中有一个点,例如:
[{...
"contact.name": "Erik Svensson",
"contact.mail": "erik.svensson@foo.bar",
"contact.phone": "0731123243",
...}]
现在,除了这些带点的字符串之外,其他所有东西都到位了,它们在我的目标类中最终为null。我猜这是因为它不知道该将它们映射到什么,因为我不能在容器类中声明一个有点的变量。
这是我正在运行的反序列化代码,
mData = new JSONDeserializer<List<Thing>>()
.use("values", Thing.class)
.deserialize(reader);
我如何修改它来捕捉带点的字符串,并将它们作为放在我的Things类中
String contactName;
String contactMail;
String contactPhone;
// getters&setters
注意,我无法控制序列化。。
好的,所以我已经解决了这个问题,但我不得不放弃flexJson。到处寻找简单的方法,但找不到。
相反,我和杰克逊一起去了,这就是我最终得到的:
ObjectMapper mapper = new ObjectMapper();
mThings = mapper.readValue(url, new TypeReference<List<Thing>>() {});
在我的课堂上,
@JsonProperty("contact.name")
private String contactName;
@JsonProperty("contact.mail")
private String contactMail;
@JsonProperty("contact.phone")
private String contactPhone;
// getters and setters..
如果有人知道如何使用FlexJson做到这一点,请随时发布答案,我很想看看。
我也很好奇,如果这种类型的任务可以轻松完成,我已经玩了一些代码,这就是我想到的。(我把它贴在这里是因为它可能对有相关问题的人有帮助,或者只是作为一个起点。)
PrefixedObjectFactory
(见下文)将从JSON对象的字段名称中截取一个固定前缀,并使用该名称查找匹配的bean属性。可以很容易地更改代码以进行替换(例如,将.
后面的第一个字母设置为大写并删除.
)
它可以这样使用:
List<Thing> l = new JSONDeserializer<List<Thing>>().use("values", new PrefixedObjectFactory(Thing.class, "contact.")).deserialize(source);
代码:
import flexjson.ObjectBinder;
import flexjson.ObjectFactory;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Type;
import java.util.Map;
public class PrefixedObjectFactory<T> implements ObjectFactory {
protected Class<T> clazz;
protected String prefix;
public PrefixedObjectFactory(Class<T> c, String prefix) {
this.clazz = c;
this.prefix = (prefix == null) ? "" : prefix;
}
@Override
public Object instantiate(ObjectBinder context, Object value, Type targetType, Class targetClass) {
try {
Class useClass = this.clazz;
T obj = (T)useClass.newInstance();
if (value instanceof Map) {
// assume that the value is provided as a map
Map m = (Map)value;
for (Object entry : m.entrySet()) {
String propName = (String)((Map.Entry)entry).getKey();
Object propValue = ((Map.Entry)entry).getValue();
propName = fixPropertyName(propName);
propValue = fixPropertyValue(propValue);
assignValueToProperty(useClass, obj, propName, propValue);
}
} else {
// TODO (left out here, to keep the code simple)
return null;
}
return obj;
} catch (Exception ex) {
return null;
}
}
protected String fixPropertyName(String propName) {
if (propName.startsWith(this.prefix)) {
propName = propName.substring(this.prefix.length());
}
return propName;
}
protected Object fixPropertyValue(Object propValue) {
return propValue;
}
protected PropertyDescriptor findPropertyDescriptor(String propName, Class clazz) {
try {
return new PropertyDescriptor(propName, clazz);
} catch (Exception ex) {
return null;
}
}
protected void assignValueToProperty(Class clazz, Object obj, String propName, Object propValue) {
try {
PropertyDescriptor propDesc = findPropertyDescriptor(propName, clazz);
if (propDesc != null) {
propDesc.getWriteMethod().invoke(obj, propValue);
}
} catch (Exception ex) {
}
}
}