fork download
  1. /* package whatever; // don't place package name! */
  2.  
  3. import java.io.IOException;
  4. import java.lang.reflect.Constructor;
  5. import java.lang.reflect.Field;
  6. import java.lang.reflect.InvocationTargetException;
  7. import java.lang.reflect.Method;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10.  
  11. class Ideone {
  12. public static void main(String[] args) throws IOException {
  13. String json = "{\"id\":1, \"name\":\"jsmith\"}";
  14. NaiveObjectMapper objectMapper = new NaiveObjectMapper();
  15. User user = objectMapper.readValue(json, User.class);
  16. System.out.println(user);
  17. }
  18.  
  19. public static class NaiveObjectMapper {
  20. private Map<String, Object> fieldsAndMethods;
  21. private NaiveJsonParser parser;
  22.  
  23. public <T> T readValue(String content, Class<T> valueType) {
  24. parser = new NaiveJsonParser(content);
  25.  
  26. try {
  27. // aggregate all value type fields and methods inside a map
  28. fieldsAndMethods = new HashMap<>();
  29. for (Field field : valueType.getDeclaredFields()) {
  30. fieldsAndMethods.put(field.getName(), field);
  31. }
  32. for (Method method : valueType.getMethods()) {
  33. fieldsAndMethods.put(method.getName(), method);
  34. }
  35.  
  36. // create an instance of value type by calling its default constructor
  37. Constructor<T> constructor = valueType.getConstructor();
  38. Object bean = constructor.newInstance(new Object[0]);
  39.  
  40. // loop through all json nodes
  41. String propName;
  42. while ((propName = parser.nextFieldName()) != null) {
  43. // find the corresponding field
  44. Field prop = (Field) fieldsAndMethods.get(propName);
  45. // get and set field value
  46. deserializeAndSet(prop, bean);
  47. }
  48. return (T) bean;
  49. } catch (NoSuchMethodException e) {
  50. e.printStackTrace();
  51. } catch (IllegalAccessException e) {
  52. e.printStackTrace();
  53. } catch (InstantiationException e) {
  54. e.printStackTrace();
  55. e.printStackTrace();
  56. }
  57.  
  58. return null;
  59. }
  60.  
  61. private void deserializeAndSet(Field prop, Object bean) {
  62. Class<?> propType = prop.getType();
  63. Method setter = (Method) fieldsAndMethods.get(getFieldSetterName(prop));
  64. try {
  65. if (propType.isPrimitive()) {
  66. if (propType.getName().equals("int")) {
  67. setter.invoke(bean, parser.getIntValue());
  68. }
  69. } else if (propType == String.class) {
  70. setter.invoke(bean, parser.getTextValue());
  71. }
  72. } catch (IllegalAccessException e) {
  73. e.printStackTrace();
  74. e.printStackTrace();
  75. }
  76. }
  77.  
  78. private String getFieldSetterName(Field prop) {
  79. String propName = prop.getName();
  80. return "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
  81. }
  82. }
  83.  
  84. static class NaiveJsonParser {
  85. String[] nodes;
  86. int currentNodeIdx = -1;
  87. String currentProperty;
  88. String currentValueStr;
  89.  
  90. public NaiveJsonParser(String content) {
  91. // split the content into 'property:value' nodes
  92. nodes = content.replaceAll("[{}]", "").split(",");
  93. }
  94.  
  95. public String nextFieldName() {
  96. if ((++currentNodeIdx) >= nodes.length) {
  97. return null;
  98. }
  99. String[] propertyAndValue = nodes[currentNodeIdx].split(":");
  100. currentProperty = propertyAndValue[0].replace("\"", "").trim();
  101. currentValueStr = propertyAndValue[1].replace("\"", "").trim();
  102. return currentProperty;
  103. }
  104.  
  105. public String getTextValue() {
  106. return String.valueOf(currentValueStr);
  107. }
  108.  
  109. public int getIntValue() {
  110. return Integer.valueOf(currentValueStr).intValue();
  111. }
  112. }
  113.  
  114. public static class User {
  115. private int id;
  116. private String name;
  117.  
  118. public int getId() {
  119. return id;
  120. }
  121.  
  122. public void setId(int id) {
  123. this.id = id;
  124. }
  125.  
  126. public String getName() {
  127. return name;
  128. }
  129.  
  130. public void setName(String name) {
  131. this.name = name;
  132. }
  133.  
  134. @Override
  135. public String toString() {
  136. return "id = " + id + ", name = \"" + name + "\"";
  137. }
  138. }
  139. }
  140.  
Success #stdin #stdout 0.05s 4386816KB
stdin
Standard input is empty
stdout
id = 1, name = "jsmith"