JSON

JSON 解析和生成, TJSONValue, TJSONObject, TJSONPair, TJSONAr

字号+ 作者:H5之家 来源:H5之家 2017-07-22 16:00 我要评论( )

JSON 解析方法和规则,读取 JSON 里面特定的值,JSON 类的继承关系 C++ Builder 自带的 JSON 头文件为 #include System.JSON.hpp,下图为 JSON 类的继承关系。 这是 C++ Builder 自带的 JSON 解析,第三方 jsoncpp 库的使用在这里 JSON 的解析,只需要调用 T

JSON 解析方法和规则,读取 JSON 里面特定的值,JSON 类的继承关系

C++ Builder 自带的 JSON 头文件为 #include <System.JSON.hpp>,下图为 JSON 类的继承关系。

  这是 C++ Builder 自带的 JSON 解析,第三方 jsoncpp 库的使用在这里

JSON 的解析,只需要调用 TJSONObject::ParseJSONValue() 函数,例如:

TJSONValue *lpJson = TJSONObject::ParseJSONValue(Memo1->Text);

这是把 Memo1->Text 的内容解析为 lpJson,这个解析之后的内容是在解析过程中 new 出来的,用完不要忘记 delete 掉。
在解析之后的数据里面,都是用 TJSONValue 这个公共的父类指针保存的数据,而实际的内容,可能是它的几个子类之一。

如上面框里面的代码,刚解析完的 lpJson 一般都是结构体类型的,即 TJSONObject,里面包含很多的成对的键名和键值,即 TJSONPair。

TJSONObject *lpRoot = dynamic_cast<TJSONObject *>(lpJson);

上面的代码,就是把第一段代码解析出来的 lpJson 转为 TJSONObject 类型的 lpRoot,即 JSON 的根节点,是一个结构体。

{
   "name":"JSON测试程序,支持UNICODE哦",
   "desc": "Copyright Victor Chen, ",
    "strval": "中文Ting Vit",
    "整数值": 12345,
    "arrval":["人民币","欧元","英镑","$美元"],
    "strarr":
    [
      { "path": "fmn061/20111118/", "desc":"啊哦" },
      { "path": "abc/def/ghi", "desc": "abcd"}
    ]
}

假定有上面这一段 JSON 内容,用前面的代码解析到了 lpRoot 里面,然后要读取里面的值:

从结构体 (TJSONObject) 里面读出值来,直接用 Values[L"键名"] 就可以得到 TJSONValue * 类型的值,
如果 TJSONValue * 里面是单个值,用 Value() 可以简单的获取值到一个字符串里面,例如:

UnicodeString sName   = lpRoot->Values[L"name"  ]->Value();
UnicodeString sStrVal = lpRoot->Values[L"strval"]->Value();
UnicodeString sIntVal = lpRoot->Values[L"整数值"]->Value();

如果 TJSONValue * 里面是数组,要把这个类型转为 TJSONArray * 类型,用 Items[i] 读出第 i 个值,也是 TJSONValue * 类型的:
我们已经知道了 arrval 是数组,下面的代码简单的说明了数据类型的转换过程,读出 arrval[1] 的值:
红色部分,是强制转换 (因为我们已经知道是数组了) lpRoot->Values[L"arrval"] 转为 TJSONArray * 类型的。

UnicodeString sArrVal1 = ((TJSONArray*)(lpRoot->Values[L"arrval"]))->Items[1]->Value();

下面再看数组里面的元素是结构体的情况,读出 strarr[0].path 和 strarr[0].desc:
红色部分,是 strarr 转为 TJSONArray * 类型,蓝色是 strarr[0] 转为 TJSONObject * 类型的,然后读出 strarr[0].path 的值。

sStrArr0path = ((TJSONObject*)((TJSONArray*)(lpRoot->Values[L"strarr"]))->Items[0])->Values[L"path"]->Value();
sStrArr0desc = ((TJSONObject*)((TJSONArray*)(lpRoot->Values[L"strarr"]))->Items[0])->Values[L"desc"]->Value();

注意!以上三段代码仅仅是为大家介绍这些类型的转换规则,在实际应用中,这样做是不严谨的,容易出现错误。
最简单的,以这句代码为例:

UnicodeString sStrVal = lpRoot->Values[L"strval"]->Value();

如果 JSON 里面没有 strval 这个值,那么 lpRoot->Values[L"strval"] 是一个 NULL 值,再用 ->Value(); 就变成 “读取空指针” 错误了。
所以在实际应用中,每一步都要判断返回的 TJSONValue *  是否为 NULL 值,即那个键值是否存在。
所以,关键字可能会不存在,应该这样做:

TJSONValue *lpValue = lpRoot->Values[L"strval"];
if(lpValue) // 如果有 strval 这个关键字
{
  sStrVal = lpValue->Value(); // 获取键值
}

 

TJSONValue

从 JSON 解析出来的值,都是使用 TJSONValue * 指针保存的,但是实际的内容,可能是它的以下子类之一:
  TJSONObject 结构体,用它的成员 Values[L"键名"] 获取键值,一共有 Count 对键名/键值,第 i 对键名/键值为 Pairs[i]
  TJSONArray  数组,用它的成员 Items[i] 获取第 i 个值,一共有 Count 个值
  TJSONString 字符串,用它的成员 Value() 获取字符串值
  TJSONNumber 数字,用 AsInt, AsInt64, AsDouble 获取整数或浮点数值,也可以用 Value() 获取值的字符串
  TJSONBool   布尔,用 AsBoolean 获取 bool 值,也可以用 Value() 获取值的字符串。
   TJSONBool   可能是它的子类 TJSONTrue 或 TJSONFalse 之一,用 dynamic_cast 可以转换或判断。
  TJSONNull   空,它的成员 Value() 为从父类继承过来的,获取到空的字符串。

可以看到,只有 TJSONObject 和 TJSONArray 不能用 Value() 获取值,其他情况都能用 Value() 获取到正确的值,所以:

  TJSONValue *lpJSONValue = 解析出来的值;
  TJSONObject *lpJSONObject = dynamic_cast<TJSONObject *>(lpJSONValue);
  TJSONArray *lpJSONArray = dynamic_cast<TJSONArray *>(lpJSONValue);
  if(lpJSONObject)
  {
    // 按照结构体解析 lpJSONObject
  }
  else if(lpJSONArray)
  {
    // 按照数组解析 lpJSONArray
  }
  else
  {
    UnicodeString sValue = lpJSONValue->Value(); // 只要不是 TJSONObject 和 TJSONArray 就能用 Value() 获取到值
  }

 

TJSONObject

TJSONObject 是结构体,是一组键名/键值的集合。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • golang json的大小写技巧

    golang json的大小写技巧

    2017-07-22 16:06

  •  WinJS实用开发技巧(1):XML转JSON

    WinJS实用开发技巧(1):XML转JSON

    2017-07-22 15:03

  • Golang中使用JSON的一些小技巧

    Golang中使用JSON的一些小技巧

    2017-07-22 09:01

  • PHP API接口必备之输出json格式数据示例教程

    PHP API接口必备之输出json格式数据示例教程

    2017-07-21 17:00

网友点评