7.4 JSON Support

The Limax provides the complete JSON support (the Java, C#, C++ and Lua versions all provide the JSON support which is consistent with the Javascript, and maximumly ensure the usage is the same with Javascript), to communicate with the other json supported third party system.


  • 7.4.1 Encoding

    Javascript JSON.stringify(obj)
    Java String limax.codec.JSON.stringify(Object obj);
    C# string limax.codec.JSON.stringify(object obj);
    C++

    std::string limax::JSON::stringify(const T& object);

    std::string limax::JSON::stringify(const char *obj);

    std::string limax::JSON::stringify(std::shared_ptr<limax::JSON> obj);

    Lua JSON.stringify(obj)

    In C++ and Lua, UTF8 encoded string is needed.


    • Type Mapping

      Javascript Java C# C++ Lua
      Number

      byte

      Byte

      sbyte

      SByte

      int8_t

      Number

      byte

      Byte

      uint8_t

      short

      Short

      short

      Int16

      int16_t

      ushort

      UInt16

      uint16_t

      int

      Integer

      AtomicInteger

      int

      Int32

      int32_t

      uint

      UInt32

      uint32_t

      long

      Long

      AtomicLong

      long

      Int64

      int64_t

      ulong

      UInt64

      uint64_t

      float

      Float

      float

      Float

      float

      double

      Double

      double

      Double

      double
      boolean

      boolean

      Boolean

      AtomicBoolean

      bool

      bool

      bool boolean
      string

       

       

       

      char

      Character

       

      String

       

       

       

      char

      Char

      string

      String

      char

      const char*

      const std::string&

       

      string
      Array

      java.reflect.Array

      Collection

      IEnumerable

      std::list<T>

      std::vector<T>

      std::deque<T>

      std::unordered_set<T>

      std::set<T>

      table
      object

      JSONSerializable

      JSONMarshal

      Map

      JSONSerializable

      JSONMarshal

      IDictionary

       

      JSONMarshal

      std::unordered_map<K,V>

      std::map<K,V>

      table
      null null null

       

       

      JSON

       

       

       

      JSON

       

      const JSON&

      std::shared_ptr<JSON>

      Note: the object corresponding to the JSON specification is written as the JSON/Object in the following document to avoid the confusion with the JSON Object constructed by the JSON class implmented by the Java, C# and C++. The array is written as the JSON/Array, and so on. All these are called as the JSON components

      1. The java.reflect.Array of the Java corresponds the native array, and Collection corresponds to all kinds of Collection containers.

      2. All the containers and native array of the C# are derived from the IEnumerable, so the IDictionary comparison has the priority to be executed when encoding to distinguish whether it is necessary to encode based on JSON/Object.

      3. The C++ version does not support any type native array, in the other words does not support the object pointed to by the pointer. The support of the const char* is only the grammar sugar, and the parameters are immediately converted to the std::string before they enter the encoder. Because the object pointed to by the pointer is not supported, the null would not be generated, except the null() method of JSONBuilder is used manually to encode a null or execute the relay. Please refer the following content.

      4. The usage of the table in the Lua is a mess, and the encoder distinguishes the JSON/Array from JSON/Object through #table>0. If the correct encoding is necessary, it should not mix the array operation and object operation on a table. Lua’s nil is interpreted as null.

      5. The null is not beneficial to the interoperability of each language version. In order to reduce the unncessary issue, it should be avoid to use.

      6. When the associative containers Map, IDictionary, std::unordered_map<K,V>, std::map<K,V>, and table are encoded as the JSON/Object, the key of them is cast to the string and encoded as JSON/String. If the container defines the key of non-string type, it should take care to verify whether the convertion result is wanted.

      7. If the encoding result is submitted to the Javascipt for handling, it must be noted that the Number of the Javascript supports maximum 53 bits integer.

      8. The last line of the table has no correspondance of the Javascript. It is used by the Java, C# and C++ when executing the relay tasks of the JSON. Please refer the follwing content.


    • Implementation of the code generation (Java, C#, C++)

      The Java, C# and C++ three types of languages use JSONMarshal and JSONBuilder to interact and complete the JSON/Object encoding. In the Limax environment, the JSONMarshal.marshal method of the detailed object could be implemented through generating code, only if the json attribute is correctly used in the xml description of the bean, cbean, xbean and protocol. For example:


      	<bean name="JChild" json="true">
      		<variable name="val" type="string"/>
      	</bean>
      
      	<bean name="JBean" json="true">
      		<variable name="intset" type="set" value="int"/>
      		<variable name="child" type="JChild"/>
      		<variable name="ignore" type="binary" json="false"/>
      	</bean>
      

      Use the generated JBean type object, call the static stringify method of the JSON class, the similar following output result could be gotten:


      	{"intset":[1,2],"child":{"val":"it's child"}}
      

      The atrribute json="true" is set on the bean, cbean, xbean and protocol elements, which allows the JSON/Object encoding code to be generated in correspond class source, and meanwhile the json attribute of the variable element is true as default, except that the variable sets the attribute json="false" manullly to turn off the relative field of this element to generate code. The JBean.ignore field of the above example is ignored during the encoding.


      When the code is generated, the xml description is strictly checked to ensure that this JSON/Object encoding code is generated legitimately, or throw the exception and stop generating. In detail, there is three cases:

      1. use the binary type

      2. use the any type

      3. referred bean does not turn on json="true"


    • Implementation of the reflection (Java, C#)

      The Java and C# support the reflection, only implementing the JSONSerializable tag interface when defining the class, the object supporting this tag is directly explained as the JSON/Object when encoding, and the field name is the key of the JSON/Object. This example defines two Java classes:


      	public class JChild implements JSONSerializable {
      		private String val = "it's child";
      	}
      
      	public class JBean implements JSONSerializable {
      		private int intset[] = new int[] { 1, 2 };
      		private JChild child = new JChild();
      		private transient Octets ignore;
      	}
      

      System.out.println(JSON.stringify(new JBean())) outputs the same result as the above example.

      The keyword transient of the Java here prevents the encoding of the ignore field. It should be noted that the C# has no similar specification. In particular, the attribute field defined in the C# class will obtain a internal encoding filed name of the C# when reflecting, and the class which needs the JSON to encode should avoid using such attribute field.。


      The encoder only considers the class itself of the object and does not consider the base class when executing the reflecting, even though the base class also implements the JSONSerializable interface.


      If the reflected field type has not been list in the table of the type mapping party, the JSONException exception will be thrown when encoding and encoding fails. Please refer the following content --- exception specification for the detailed information.


    • Implementation of the associative containers (Java, C#, C++)

      Directly encode an associative container.

      For example, Java code:


      	Map<String, Object> jchild = new HashMap<>();
      	jchild.put("val", "it's child");
      	Map<String, Object> jbean = new HashMap<>();
      	jbean.put("intset", new int[]{1,2});
      	jbean.put("child", jchild);
      	System.out.println(JSON.stringify(jbean));
      

      The similar result as the above example could be output.


      The basic type of the C++ lacks a common base class, so the above result could not be achieved.


      	std::unordered_map<std::string, std::string> jchild;
      	jchild.insert(std::make_pair("val", "it's child"));
      	std::unordered_map<std::string, std::unordered_map<std::string, std::string>> jbean;
      	jbean.insert(std::make_pair("child", jchild));
      	printf("%s\n", JSON::stringify(jbean).c_str());
      

      Only the regular result could be obtained:


      	{"child":{"val":"it's child"}}
      

      Conclusion:

      1. In most condition, the C++ only applies the code generation or manual implemention through referencing the generated code.

      2. Compared with the generating code and reflection, the associative container has worse readability and is not worth using except for the special case.


Prev Next