我正在创建java应用程序,它将允许在数据库中存储对象。我想做的是通用实现,这样它就可以加载 json 并从中创建 java 类。代码应该是这样的:
SomeClass someObject= data.getValue(SomeClass.class);
假设数据是一个 json 对象。我应该如何实现 getValue() 方法,以便它允许我从中创建类。我不希望 SomeClass
扩展 Object
之外的任何内容。我认为这应该使用泛型类来完成,但到目前为止我还没有使用过这样的泛型类。您能指出实现这一目标的最佳方法吗?最好有示例代码。
非常感谢
最佳答案
您可以查阅 Jackson 库的源代码并查看(或调试)方法 BeanDeserializer#vanillaDeserialize() ,你会发现循环遍历所有 json 标记,找到相应的字段并设置它们的值。
作为概念证明,我从 Jacskson 中提取了部分逻辑,并将其包装在一个幼稚(且脆弱)的对象映射器和一个幼稚(且脆弱)的 json 解析器中:
public static class NaiveObjectMapper {
private Map<String, Object> fieldsAndMethods;
private NaiveJsonParser parser;
public <T> T readValue(String content, Class<T> valueType) {
parser = new NaiveJsonParser(content);
try {
// aggregate all value type fields and methods inside a map
fieldsAndMethods = new HashMap<>();
for (Field field : valueType.getDeclaredFields()) {
fieldsAndMethods.put(field.getName(), field);
}
for (Method method : valueType.getMethods()) {
fieldsAndMethods.put(method.getName(), method);
}
// create an instance of value type by calling its default constructor
Constructor<T> constructor = valueType.getConstructor();
Object bean = constructor.newInstance(new Object[0]);
// loop through all json nodes
String propName;
while ((propName = parser.nextFieldName()) != null) {
// find the corresponding field
Field prop = (Field) fieldsAndMethods.get(propName);
// get and set field value
deserializeAndSet(prop, bean);
}
return (T) bean;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
private void deserializeAndSet(Field prop, Object bean) {
Class<?> propType = prop.getType();
Method setter = (Method) fieldsAndMethods.get(getFieldSetterName(prop));
try {
if (propType.isPrimitive()) {
if (propType.getName().equals("int")) {
setter.invoke(bean, parser.getIntValue());
}
} else if (propType == String.class) {
setter.invoke(bean, parser.getTextValue());
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
private String getFieldSetterName(Field prop) {
String propName = prop.getName();
return "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
}
}
class NaiveJsonParser {
String[] nodes;
int currentNodeIdx = -1;
String currentProperty;
String currentValueStr;
public NaiveJsonParser(String content) {
// split the content into 'property:value' nodes
nodes = content.replaceAll("[{}]", "").split(",");
}
public String nextFieldName() {
if ((++currentNodeIdx) >= nodes.length) {
return null;
}
String[] propertyAndValue = nodes[currentNodeIdx].split(":");
currentProperty = propertyAndValue[0].replace("\"", "").trim();
currentValueStr = propertyAndValue[1].replace("\"", "").trim();
return currentProperty;
}
public String getTextValue() {
return String.valueOf(currentValueStr);
}
public int getIntValue() {
return Integer.valueOf(currentValueStr).intValue();
}
}
public static class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "id = " + id + ", name = \"" + name + "\"";
}
}
要查看运行中的反序列化:
String json = "{\"id\":1, \"name\":\"jsmith\"}";
NaiveObjectMapper objectMapper = new NaiveObjectMapper();
User user = objectMapper.readValue(json, User.class);
System.out.println(user);
或者尝试online .
但是,我建议不要重新发明轮子并使用 Jackson,如果您需要一些自定义操作,您可以使用自定义反序列化,请参阅 here和 here 。
关于Java 使用 .class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45534810/