Java 使用 .class

标签 java class generics

我正在创建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,如果您需要一些自定义操作,您可以使用自定义反序列化,请参阅 herehere

关于Java 使用 .class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45534810/

相关文章:

java - RabbitMQ 队列和路由键

java - 我可以在运行时创建一个java类吗

swift - 在 Swift 中初始化类属性

java - 用映射替换 switch 语句(针对不同的数据类型)

java - 是否可以在反射的帮助下重建通用返回类型 - Java?

java - 标记语法错误,错误放置的结构

java - 调试动态代理创建会改变调用处理程序状态

java - 特定于区域设置的时间和日期格式,包括毫秒

Java:一个类是它自己的子类吗?

java - 使用通配符和类型化泛型会生成 "is not applicable for the arguments"错误