当前位置: 首页 > news >正文

做旅游网站多少钱/劳动局免费培训项目

做旅游网站多少钱,劳动局免费培训项目,做国外商品的网站,全网营销概念在了解JSON协议之前,朋友们可以先去了解一下JSON的基础知识,和ASCII基本分布,关于JSON一些常识请见这里; JSON (JavaScript Object Notation)是一种数据交换格式,是以JavaScript为基础的数据表示语言,是在以下两种数据…

      在了解JSON协议之前,朋友们可以先去了解一下JSON的基础知识,和ASCII基本分布,关于JSON一些常识请见这里;

      JSON (JavaScript Object Notation)是一种数据交换格式,是以JavaScript为基础的数据表示语言,是在以下两种数据结构的基础上来定义基本的数据描述格式的:1) 含有名称/值对的Object;2) 以”[“,",","]"组成的数组。对于 JSON,下例:形如{“name”:”tom”,”age”:23}就表示一个JSON 对象,其有两个属性,值分别为tom和23。key必须为string。JSON支持的基本数据类型,包括Number,Boolean,  null, String;  boolean, null类型值不能加” “,不然会当做string来出来,再通过object, array来组合成丰富的类型结构。

    来看看Thrift中JSON常用标签的定义:

  private static final byte[] COMMA = new byte[] {','};      //json object中键值对之间, json array中元素之间的private static final byte[] COLON = new byte[] {':'};       //json object中key : valueprivate static final byte[] LBRACE = new byte[] {'{'};      //json object开始标签private static final byte[] RBRACE = new byte[] {'}'};      //json object结束标签private static final byte[] LBRACKET = new byte[] {'['};    //json array开始标签private static final byte[] RBRACKET = new byte[] {']'};    //json array结束标签private static final byte[] QUOTE = new byte[] {'"'};       //json 字符串标签private static final byte[] BACKSLASH = new byte[] {'\\'};   //json中转义private static final byte[] ZERO = new byte[] {'0'};        // 0字符

      Unicode编码形式:

private static final byte[] ESCSEQ = new byte[] {'\\','u','0','0'};

      JSON中字符串是由双引号包围的任意数量的unicode字符结合,当然还要包含通过'\'转义字符(不多),如下;

  private static final String ESCAPE_CHARS = "\"\\/bfnrt";    //需要转义的字符 '"' , '\' , ' /' ,'b' , 'f' , 'n' ,'r' ,'t'private static final byte[] ESCAPE_CHAR_VALS = {'"', '\\', '/', '\b', '\f', '\n', '\r', '\t', // 转义字符对应的字节数组};

    ASCII表前48字符表:

1   private static final byte[] JSON_CHAR_TABLE = {
2     /*  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
3         0,  0,  0,  0,  0,  0,  0,  0,'b','t','n',  0,'f','r',  0,  0, // 0
4         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 1
5         1,  1,'"',  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, // 2
6   };

     前48个字符中,值为0的是一些不常用的控制字符,所以这里标为0,unicode输出;值为1的为那些可显示非转义字符,输出时直接按其ASCII编码值输出即可;其他的是需要转义的字符,按照上面的转义字符的字节数组输出,

下面是ASCII编码图,朋友们可以参照着看一下:

 

     下面是Thrift内部数据类型对应的JSON输出字节数组标志,在write和read时,会按照其进行相应的转换,源码时,具体分析:

  private static final byte[] NAME_BOOL = new byte[] {'t', 'f'};private static final byte[] NAME_BYTE = new byte[] {'i','8'};private static final byte[] NAME_I16 = new byte[] {'i','1','6'};private static final byte[] NAME_I32 = new byte[] {'i','3','2'};private static final byte[] NAME_I64 = new byte[] {'i','6','4'};private static final byte[] NAME_DOUBLE = new byte[] {'d','b','l'};private static final byte[] NAME_STRUCT = new byte[] {'r','e','c'};private static final byte[] NAME_STRING = new byte[] {'s','t','r'};private static final byte[] NAME_MAP = new byte[] {'m','a','p'};private static final byte[] NAME_LIST = new byte[] {'l','s','t'};private static final byte[] NAME_SET = new byte[] {'s','e','t'};

      基本重要数据成员介绍完毕,在具体分析读写前,再来介绍下写辅助方法和类,有助于后面读写的具体理解:

// 把char('0 - 9' & ' a - f')字符转变为相应的hex十六进制值。private static final byte hexVal(byte ch) throws TException {if ((ch >= '0') && (ch <= '9')) {return (byte)((char)ch - '0');}else if ((ch >= 'a') && (ch <= 'f')) {return (byte)((char)ch - 'a' + 10);}else {throw new TProtocolException(TProtocolException.INVALID_DATA,"Expected hex character");}}// 上面的反过程,把hex十六进制值转变为相应的字符。private static final byte hexChar(byte val) {val &= 0x0F;if (val < 10) {return (byte)((char)val + '0');}else {return (byte)((char)(val - 10) + 'a');}}

     辅助类,用于具体读写过程中写入,或读取JSON语法字符,该类为基类,no-op:

 protected class JSONBaseContext {protected void write() throws TException {}protected void read() throws TException {}protected boolean escapeNum() { return false; }}

     用于读取JSON数组的JSONBASEContext子类, 用于写入,读取元素item之间的JSON语法字符 ' ,':

 protected class JSONListContext extends JSONBaseContext {private boolean first_ = true;  //第一个元素之前不要添加,读取 ',';@Overrideprotected void write() throws TException {if (first_) {first_ = false;} else {trans_.write(COMMA);}}@Overrideprotected void read() throws TException {if (first_) {first_ = false;} else {readJSONSyntaxChar(COMMA);}}}

     用于读取JSON 对象(Object)的JSONBASEContext子类,  用于写入,读取元素item之间的 ' ,' , 和key, value对之间的 ':' JSON语法字符:

  protected class JSONPairContext extends JSONBaseContext {private boolean first_ = true;   //添加,读取 ','字符的标志,第一个不需要加入和读取;private boolean colon_ = true;   //添加,读取 ':'字符的标志,@Overrideprotected void write() throws TException {if (first_) {first_ = false;colon_ = true;} else {trans_.write(colon_ ? COLON : COMMA);colon_ = !colon_;}}@Overrideprotected void read() throws TException {if (first_) {first_ = false;colon_ = true;} else {readJSONSyntaxChar(colon_ ? COLON : COMMA);colon_ = !colon_;}}@Overrideprotected boolean escapeNum() { //由于JSON Object的key必须为string类型,所以这里用colon标志,同时标注是否需要写入,读取'"'字符;return colon_;}}

   

private Stack<JSONBaseContext> contextStack_ = new Stack<JSONBaseContext>(); //用于读取不同类型时,上下文上下切换,上面提及的两种上下文,读取和写入JSON Object,和JSON array,当递归解析和写入时,得随时切换
private JSONBaseContext context_ = new JSONBaseContext(); //当前读取,写入上下文。
//private void pushContext(JSONBaseContext c) { //吧方法参数的上下文设为当前上下文(比如当前真在解析JSON array,而array中出现一个JOSN object(map) item时,得切换到JSONPairContext来解析)contextStack_.push(context_); //当前上下文压入栈,context_ = c;}private void popContext() {context_ = contextStack_.pop(); //吧之前压入栈的上下文设为当前上下文(还是上面的例子,当JSON object解析完后,接着解析array别的item,所以还得之前压入栈的上下文)}

 

       上面两个类都用到readJSONSyntaxChar(xxx)方法,我们再来看看:

 protected void readJSONSyntaxChar(byte[] b) throws TException {byte ch = reader_.read();     //方法参数设定一个字节数组,当读取的字节不等于b[0]抛异常,要来验证读取的字节是否为指定的JSON语句字符的。if (ch != b[0]) {throw new TProtocolException(TProtocolException.INVALID_DATA,"Unexpected character:" + (char)ch);}}

       JOSN协议从传输层读取字节时都是一字节一字节的读取:

 protected class LookaheadReader {private boolean hasData_;private byte[] data_ = new byte[1];//检测当前容量为1的字节数组中是否有数据,没有从底层传输层读取一字节,该方法是消耗型的protected byte read() throws TException {if (hasData_) {hasData_ = false;}else {trans_.readAll(data_, 0, 1);}return data_[0];}// 同上,不同的是该方法不发生消耗protected byte peek() throws TException {if (!hasData_) {trans_.readAll(data_, 0, 1);}hasData_ = true;return data_[0];}}

     别的参数成员:

 // 上面已经介绍,当前解析的底层读取器,一个字节一个字节的读取private LookaheadReader reader_ = new LookaheadReader();// 是否写入TField的(即方法参数的参数名)的标志,不写入参数名,就要参数标号来代替private boolean fieldNamesAsString_ = false;

    OK!进入正文,首先看看JSON协议怎么写数据的,从string开始,JSON String分Unicode和转义字符两种:

 private void writeJSONString(byte[] b) throws TException {context_.write(); // JSONBaseContext 空操作trans_.write(QUOTE); //写入'"'字符int len = b.length;  for (int i = 0; i < len; i++) {if ((b[i] & 0x00FF) >= 0x30) { //对照上面的ASCII表, >= 0x30即 >= 48(上面JSON_CHAR_TABLE表述的为0 - 47,48以上的用的着的转义字符就'\')if (b[i] == BACKSLASH[0]) { //如果写入的字符为 '\',需要转义。trans_.write(BACKSLASH);//trans_.write(BACKSLASH); // 写两次'\'
        }else {trans_.write(b, i, 1);// 0x30上除'\',之外的字符直接写入
        }}else { // b[i] < 48的情况,即上面设计的那张JSON_CHAR_TABLE倍tmpbuf_[0] = JSON_CHAR_TABLE[b[i]];  if (tmpbuf_[0] == 1) {       //查表后,表对应的值为1的情况:非转义,即可直接写入。trans_.write(b, i, 1);}else if (tmpbuf_[0] > 1) {     //即为那些转义字符 '"' , '/' , 'b' , 't' , 'r' , 'n';trans_.write(BACKSLASH); // 写之前先追加'\';trans_.write(tmpbuf_, 0, 1);}else { // 0trans_.write(ESCSEQ);//unicode   \u00xx形式写入。tmpbuf_[0] = hexChar((byte)(b[i] >> 4)); tmpbuf_[1] = hexChar(b[i]);trans_.write(tmpbuf_, 0, 2);}}}trans_.write(QUOTE);  // 最后再加上'"';}

      JSON 整形输出:

private void writeJSONInteger(long num) throws TException { //虽然这里取long的字符串表现形式,但是输出是按JSON 整数表示输出(没加 '"');context_.write();  //no -opString str = Long.toString(num); //string表示形式boolean escapeNum = context_.escapeNum();  //falseif (escapeNum) {trans_.write(QUOTE);  }try {  byte[] buf = str.getBytes("UTF-8");  //UTF-8字符编码得到字节数组trans_.write(buf);} catch (UnsupportedEncodingException uex) {throw new TException("JVM DOES NOT SUPPORT UTF-8");}if (escapeNum) {trans_.write(QUOTE);}}

     JSON 浮点数写入,JSON浮点数有几点特殊,JSON几种特殊的浮点数用字符串表示和传输:

     a. NaN表示不是数字值;

     b. Infinity表示正无穷大;

     c. –Infinity表示负无穷大。

private void writeJSONDouble(double num) throws TException {context_.write();String str = Double.toString(num);boolean special = false;switch (str.charAt(0)) {case 'N': // NaNcase 'I': // Infinityspecial = true;break;case '-':if (str.charAt(1) == 'I') { // -Infinityspecial = true;}break;default:break;}boolean escapeNum = special || context_.escapeNum();  //三种特殊情况,special标志位true,此时escapeNum为true, 即用JSON字符串形式表示和输出,否则还是以JSON Number类型输出if (escapeNum) {trans_.write(QUOTE); // '"'}try {byte[] b = str.getBytes("UTF-8");trans_.write(b, 0, b.length);} catch (UnsupportedEncodingException uex) {throw new TException("JVM DOES NOT SUPPORT UTF-8");}if (escapeNum) {trans_.write(QUOTE); // '"'}}

       Thrift的二进制值并编码为base64编码然后作为JSON的字符串:

   public void writeBinary(ByteBuffer bin) throws TException {
      writeJSONBase64(bin.array(), bin.position() + bin.arrayOffset(), bin.limit() - bin.position() - bin.arrayOffset());
   }


private void writeJSONBase64(byte[] b, int offset, int length) throws TException {context_.write();trans_.write(QUOTE);int len = length;int off = offset;while (len >= 3) {// Encode 3 bytes at a timeTBase64Utils.encode(b, off, 3, tmpbuf_, 0);trans_.write(tmpbuf_, 0, 4);off += 3;len -= 3;}if (len > 0) {// Encode remainderTBase64Utils.encode(b, off, len, tmpbuf_, 0);trans_.write(tmpbuf_, 0, len + 1);}trans_.write(QUOTE);}

      Thrift的bool类型写入方式是按JSON 整形写入,false = 0 , ture = 1:

public void writeBool(boolean b) throws TException {writeJSONInteger(b ? (long)1 : (long)0);}

    Thrift其他整型和字节写入方式一并贴出,转换为long类型,都是按JSON整形写入:

 @Overridepublic void writeByte(byte b) throws TException {writeJSONInteger((long)b);}@Overridepublic void writeI16(short i16) throws TException {writeJSONInteger((long)i16);}@Overridepublic void writeI32(int i32) throws TException {writeJSONInteger((long)i32);}@Overridepublic void writeI64(long i64) throws TException {writeJSONInteger(i64);}

   Thrift的double类型,按照JSON浮点数写入:

 public void writeDouble(double dub) throws TException {writeJSONDouble(dub);}

   Thrift的string类型按照JSON字符串写入,JSON在处理时,会对一些字符进行转义:

 public void writeString(String str) throws TException {try {byte[] b = str.getBytes("UTF-8"); //string utf-8编码之后得到字节数组writeJSONString(b);} catch (UnsupportedEncodingException uex) {throw new TException("JVM DOES NOT SUPPORT UTF-8");}}

    再来看看Thrift 的set , list写入方法:

  @Overridepublic void writeListBegin(TList list) throws TException {writeJSONArrayStart();writeJSONString(getTypeNameForTypeID(list.elemType));writeJSONInteger(list.size);}@Overridepublic void writeListEnd() throws TException {writeJSONArrayEnd();}@Overridepublic void writeSetBegin(TSet set) throws TException {writeJSONArrayStart();writeJSONString(getTypeNameForTypeID(set.elemType));writeJSONInteger(set.size);}@Overridepublic void writeSetEnd() throws TException {writeJSONArrayEnd();}

     Thrift的lists和sets被表示为JSON的array(数组),其中数组的第一个元素表示Thrift元素的数据类型,数组第二值表示后面Thrift元素的个数。接着后面就是所有的元素:

  private void writeJSONArrayStart() throws TException {context_.write();trans_.write(LBRACKET);  //写入JSON array语法字符 ‘[’pushContext(new JSONListContext()); //设置当前处理解析上下文,}private void writeJSONArrayEnd() throws TException {popContext();   //回复之前的处理解析上下文trans_.write(RBRACKET);  //补上JSON array语句结束字符']'}

      数组的第一个元素为数据类型,按JSON字符串写入,即本篇开头贴出的代码,getTypeNameForTypeID(set.elemType) 用于Thrift数据类型和JSON为该类型表示的字符串的字节数组之间的转换:

 private static final byte[] getTypeNameForTypeID(byte typeID)throws TException {switch (typeID) {case TType.BOOL:return NAME_BOOL;case TType.BYTE:return NAME_BYTE;case TType.I16:return NAME_I16;case TType.I32:return NAME_I32;case TType.I64:return NAME_I64;case TType.DOUBLE:return NAME_DOUBLE;case TType.STRING:return NAME_STRING;case TType.STRUCT:return NAME_STRUCT;case TType.MAP:return NAME_MAP;case TType.SET:return NAME_SET;case TType.LIST:return NAME_LIST;default:throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED,"Unrecognized type");}}

     数组的第二个元素为整个list , set的长度,按JSON整形写入,然后写入各个容器成员。

     Thrift map数据类型写入方式:

  public void writeMapBegin(TMap map) throws TException {writeJSONArrayStart(); // '[' ,设置当前处理解析上下文writeJSONString(getTypeNameForTypeID(map.keyType)); //数组的第一个元素为key类型 =>JSON的类型字符串表示字节数组writeJSONString(getTypeNameForTypeID(map.valueType)); // 数组的第二个元素  为 value类型writeJSONInteger(map.size); //数组的第三个元素,map的长度writeJSONObjectStart(); //map的key,value对按 Json object输出。}@Overridepublic void writeMapEnd() throws TException {writeJSONObjectEnd(); //回复当前上下文 ‘}’writeJSONArrayEnd(); //回复当前上下文 ']'}
  private void writeJSONObjectStart() throws TException {context_.write();trans_.write(LBRACE);pushContext(new JSONPairContext());}private void writeJSONObjectEnd() throws TException {popContext();trans_.write(RBRACE);}

       Thrift的maps被表示为JSON的array,其中前两个值分别表示键和值的类型,跟着就是键值对的个数,接着就是包含具体键值对的JSON对象了。注意了JSON的键只能是字符串,这就是要求Thrift的maps类型的键必须是数字和字符串的,并且数字和字符串做转换,就是下面提及的字符串。

       有效的类型标识是:"tf"代表 bool,"i8" 表示 byte,"i16"表示16位整数,"i32"表示32位整数,"i64"表示64位整数,"dbl"表示双精度浮点型,"str" 表示字符串(包括二进制),"rec"表示结构体 ("records"),"map"表示 map,"lst" 表示 list, "set" 表示set。

 

     Thrift的messages(消息)被表示为JSON的array,前四个元素分别代表协议版本、消息名称、消息类型和序列ID:

public void writeMessageBegin(TMessage message) throws TException {writeJSONArrayStart();writeJSONInteger(VERSION);try {byte[] b = message.name.getBytes("UTF-8");writeJSONString(b);} catch (UnsupportedEncodingException uex) {throw new TException("JVM DOES NOT SUPPORT UTF-8");}writeJSONInteger(message.type);writeJSONInteger(message.seqid);}

    然后呢?该写Thrift的tstructs了(具体的RPC方法参数封装),struct是按照JSON object写入:

public void writeStructBegin(TStruct struct) throws TException {writeJSONObjectStart();}

   Thrift的TField(具体的每个参数)的写入:

 public void writeFieldBegin(TField field) throws TException {if (fieldNamesAsString_) {writeString(field.name); //参数名} else {writeJSONInteger(field.id); //或者参数id}writeJSONObjectStart();  // '{'writeJSONString(getTypeNameForTypeID(field.type)); Thrift数据类型的字符串表示}

   即Thrift的消息类型形如:

[ 1 (version) ,   "messageName" ,  type (call, oneway, reply, exception (byte)) ,  seq id , {  "argument name" : {  " argument  type"  :  value  },"argument name" : {  " argument  type" :   value},....................................................................}
]

 

转载于:https://www.cnblogs.com/onlysun/p/4611566.html

http://www.lbrq.cn/news/733501.html

相关文章:

  • 企业网站内容运营方案策划/搜索引擎优化的基本方法
  • 无锡网站建设工作室/兰州seo新站优化招商
  • ps如何做ppt模板下载网站/百度关键词工具
  • 党建网站信息化建设实施方案/产品网络营销策划方案
  • 东营两学一做测试网站/万能软文范例800字
  • 好的网站开发自学网站/搜索引擎优化关键词
  • 深圳龙岗网络推广/青山seo排名公司
  • 联通官网/淘宝优化标题都是用什么软件
  • 江苏建设银行网站/线下引流的八种推广方式
  • 营销型网站设计方针/新浪新闻疫情
  • 易企网站建设/竞价托管哪家效果好
  • 中国建设银行官方网站手机银行/怎么推广自己的店铺
  • wordpress+视频边栏/windows优化大师下载
  • 怎样提高网站的点击率/电脑培训中心
  • 做标签网站刷单/如何做互联网营销推广
  • 网站空间买多大的/安卓手机游戏优化器
  • 中交路桥建设有限公司资质/济源新站seo关键词排名推广
  • wordpress成长记录网站模版/郑州网络营销排名
  • 网站建设书籍/做网站价格
  • 苏州做网站品牌公司/手机建立一个免费网站
  • 重庆安全监督工程信息网/上海单个关键词优化
  • oa软件开发定制/seo怎么优化软件
  • wordpress支付文件在哪里设置/郑州seo线上推广系统
  • 银川网站怎么做seo/网站优化推广招聘
  • 网页设计 网站建设 哪个好/经典软文案例100例简短
  • 福建省建设注册中心网站/腾讯广点通
  • 南通专业网站制作/seo自学网免费
  • 如何做征信公司网站/上海网站制作
  • 商机互联做网站怎么样/注册公司网上申请入口
  • 装修公司报价/seo线上培训多少钱
  • C++ this 指针
  • 粗粮厂的基于flink的汽车实时数仓解决方案
  • DRF序列化器
  • 力扣 30 天 JavaScript 挑战 第36天 第8题笔记 深入了解reduce,this
  • day31 SQLITE
  • c语言多任务处理(并发程序设计)