7.4 JSON支持

Limax提供完整的JSON支持(Java,C#,C++,Lua版本均提供与Javascript一致的JSON支持,使用上最大限度保证与javascript相同),便于同其它支持JSON的第三方系统进行交互。


  • 7.4.6 高级功能

    • 非标准JSON串(Java,C#,C++,Lua)

      某些陈旧系统的编码器,将JSON/Object串描述中的冒号写作等号,分割JSON元件的逗号写作分号,解码器可以容忍这样的输入。另外,true,false,null三个JSON元件, 解码器按大小写不敏感处理。


    • 编码流(Java,C#)


      	public static void encode(Object obj, Appendable a);
      

      JSONEncoder提供上面的方法,允许编码器与limax.codec其它流处理模块协同,直接向目的输出。


      	OutputStream os = ...;
      	JSONEncoder.encode(json, new CharSource(StandardCharsets.UTF_8, new SinkStream(os)));
      

      例如,上面的代码,将json对象编码结果,看作一个字符流源,通过UTF8编码器,编码成字节流,再发送到输出流。

      这样的过程,注意捕获异常,流中处理过程中所有异常最后都会包裹到JSONException中然后抛出。


    • 流解码(Java,C#,C++)

      Java,C#,C++三个版本内部通过流方式解码,输入为字节流,而不是简单的串输入。

      1. JSONDecoder通过void accept(char c);方法获取字符输入,该方法可能抛出异常。C++版本抛出JSONException,Java版本抛出RuntimeException,C#版本抛出Exception

      2. 通过JSONDecoder()方法构造的解码对象只能解码一个JSON元件,解码完毕后通过JSON get() 方法获取JSON对象

      3. JSONDecoder(JSONConsumer consumer)方法允许提供一个consumer,获取解码后的对象(连续解码JSON元件)

      4. Java,C#版本的JSONDecoder实现了limax.codec.CharConsumer接口,允许与limax.codec其它流模块协同解码。


      例一 (Endpoint.java 中解码来自Auany的服务配置信息的方法)

      Endpoint.java


      public static List<ServiceInfo> loadServiceInfos(String httpHost, int httpPort, int appid, long timeout,	int maxsize, File cacheDir, boolean staleEnable) throws Exception {
      	JSONDecoder decoder = new JSONDecoder();
      	new HttpClient("http://" + httpHost + ":" + httpPort + "/app?native=" + appid, timeout, maxsize, cacheDir,staleEnable).transfer(new CharSink(decoder));
      	List<ServiceInfo> services = new ArrayList<ServiceInfo>();
      	for (JSON json : decoder.get().get("services").toArray())
      		services.add(new ServiceInfo(appid, json));
      	return services;
      }
      

      在这里HttpClient下载指定url的内容,通过CharSink适配,将字节流传送给解码器,之后在解码器上执行get(),获取JSON对象。 解码器套上适配器后, 异常处理只需要考虑最外层,在这里就是HttpClient.transfer抛出的IOException。之后的JSON访问可能抛出JSONException,整个方法简单处理,指示抛出Exception。


      例二(C++实现的多JSON解码)


      JSONDecoder jd([](std::shared_ptr<JSON> json) {printf("%s\n", json->toString().c_str()); });
      for (auto c : std::string("{\"a\":10}[2,3]5[12]"))
      	jd.accept(c);
      

      这个例子会输出如下4行:

      <Object>

      <Array>

      5

      <Array>

      输出结果刚好反映了JSON输入串的结构。需要注意的是,如果在这个串的最后添加一个数字,那么输出结果还是上面4行。流方式处理时,数字的解码比较特殊,不参考下一个字符,不可能决定该数字是否结束,不像串使用双引号结束。所以JSON.parse通过JSONDecoder实现的解码代码,在最后会调用一次JSONDecoder的内部方法flush,flush简单地accept一个空格,JSON规范规定了JSON元件之间的白空格均被忽略,用最后加入空格的方法正好解决数字的问题。另外,还必须注意JSON.parse只能解码一个JSON元件, 如果用上面代码中的串调用JSON.parse,解码器处理完毕"{\"a\":10}",遭遇到第一个非白空格,也就是之后的"[",即会抛出异常,用Javascript, Lua版本执行这样的parse同样是这个效果,各语言版本语义一致。


上一页 下一页