You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JsonEncoder.java 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.communication;
  5. import java.util.List;
  6. import java.util.Map;
  7. import com.google.gwt.json.client.JSONArray;
  8. import com.google.gwt.json.client.JSONBoolean;
  9. import com.google.gwt.json.client.JSONNull;
  10. import com.google.gwt.json.client.JSONObject;
  11. import com.google.gwt.json.client.JSONString;
  12. import com.google.gwt.json.client.JSONValue;
  13. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  14. import com.vaadin.terminal.gwt.client.ServerConnector;
  15. import com.vaadin.terminal.gwt.client.ConnectorMap;
  16. /**
  17. * Encoder for converting RPC parameters and other values to JSON for transfer
  18. * between the client and the server.
  19. *
  20. * Currently, basic data types as well as Map, String[] and Object[] are
  21. * supported, where maps and Object[] can contain other supported data types.
  22. *
  23. * TODO extensible type support
  24. *
  25. * @since 7.0
  26. */
  27. public class JsonEncoder {
  28. public static final String VTYPE_PAINTABLE = "p";
  29. public static final String VTYPE_BOOLEAN = "b";
  30. public static final String VTYPE_DOUBLE = "d";
  31. public static final String VTYPE_FLOAT = "f";
  32. public static final String VTYPE_LONG = "l";
  33. public static final String VTYPE_INTEGER = "i";
  34. public static final String VTYPE_STRING = "s";
  35. public static final String VTYPE_ARRAY = "a";
  36. public static final String VTYPE_STRINGARRAY = "c";
  37. public static final String VTYPE_MAP = "m";
  38. public static final String VTYPE_LIST = "L";
  39. // TODO is this needed?
  40. public static final String VTYPE_UNDEFINED = "u";
  41. /**
  42. * Encode a value to a JSON representation for transport from the client to
  43. * the server.
  44. *
  45. * @param value
  46. * value to convert
  47. * @param connectorMap
  48. * mapper from connectors to connector IDs
  49. * @param connection
  50. * @return JSON representation of the value
  51. */
  52. public static JSONValue encode(Object value, ConnectorMap connectorMap,
  53. ApplicationConnection connection) {
  54. if (null == value) {
  55. // TODO as undefined type?
  56. return combineTypeAndValue(VTYPE_UNDEFINED, JSONNull.getInstance());
  57. } else if (value instanceof String[]) {
  58. String[] array = (String[]) value;
  59. JSONArray jsonArray = new JSONArray();
  60. for (int i = 0; i < array.length; ++i) {
  61. jsonArray.set(i, new JSONString(array[i]));
  62. }
  63. return combineTypeAndValue(VTYPE_STRINGARRAY, jsonArray);
  64. } else if (value instanceof String) {
  65. return combineTypeAndValue(VTYPE_STRING, new JSONString(
  66. (String) value));
  67. } else if (value instanceof Boolean) {
  68. return combineTypeAndValue(VTYPE_BOOLEAN,
  69. JSONBoolean.getInstance((Boolean) value));
  70. } else if (value instanceof Object[]) {
  71. Object[] array = (Object[]) value;
  72. JSONArray jsonArray = new JSONArray();
  73. for (int i = 0; i < array.length; ++i) {
  74. // TODO handle object graph loops?
  75. jsonArray.set(i, encode(array[i], connectorMap, connection));
  76. }
  77. return combineTypeAndValue(VTYPE_ARRAY, jsonArray);
  78. } else if (value instanceof Map) {
  79. Map<String, Object> map = (Map<String, Object>) value;
  80. JSONObject jsonMap = new JSONObject();
  81. for (String mapKey : map.keySet()) {
  82. // TODO handle object graph loops?
  83. Object mapValue = map.get(mapKey);
  84. jsonMap.put(mapKey, encode(mapValue, connectorMap, connection));
  85. }
  86. return combineTypeAndValue(VTYPE_MAP, jsonMap);
  87. } else if (value instanceof ServerConnector) {
  88. ServerConnector paintable = (ServerConnector) value;
  89. return combineTypeAndValue(VTYPE_PAINTABLE, new JSONString(
  90. connectorMap.getConnectorId(paintable)));
  91. } else {
  92. if (getTransportType(value) != VTYPE_UNDEFINED) {
  93. return combineTypeAndValue(getTransportType(value),
  94. new JSONString(String.valueOf(value)));
  95. } else {
  96. // Try to find a generated serializer object, class name is the
  97. // type
  98. String type = value.getClass().getName();
  99. JSONSerializer serializer = JsonDecoder.serializerMap
  100. .getSerializer(type);
  101. // TODO handle case with no serializer found
  102. return combineTypeAndValue(type,
  103. serializer.serialize(value, connectorMap, connection));
  104. }
  105. }
  106. }
  107. private static JSONValue combineTypeAndValue(String type, JSONValue value) {
  108. JSONArray outerArray = new JSONArray();
  109. outerArray.set(0, new JSONString(type));
  110. outerArray.set(1, value);
  111. return outerArray;
  112. }
  113. private static String getTransportType(Object value) {
  114. if (value instanceof String) {
  115. return VTYPE_STRING;
  116. } else if (value instanceof ServerConnector) {
  117. return VTYPE_PAINTABLE;
  118. } else if (value instanceof Boolean) {
  119. return VTYPE_BOOLEAN;
  120. } else if (value instanceof Integer) {
  121. return VTYPE_INTEGER;
  122. } else if (value instanceof Float) {
  123. return VTYPE_FLOAT;
  124. } else if (value instanceof Double) {
  125. return VTYPE_DOUBLE;
  126. } else if (value instanceof Long) {
  127. return VTYPE_LONG;
  128. } else if (value instanceof List) {
  129. return VTYPE_LIST;
  130. } else if (value instanceof Enum) {
  131. return VTYPE_STRING; // transported as string representation
  132. } else if (value instanceof String[]) {
  133. return VTYPE_STRINGARRAY;
  134. } else if (value instanceof Object[]) {
  135. return VTYPE_ARRAY;
  136. } else if (value instanceof Map) {
  137. return VTYPE_MAP;
  138. }
  139. // TODO throw exception?
  140. return VTYPE_UNDEFINED;
  141. }
  142. }