[序列化协议] --- JSON

本文涉及的产品
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: [序列化协议] --- JSON

1. json的基础语法和规范

1.1 json是什么

- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
- JSON 具有自我描述性,更易理解

1.2 JSON基本语法规则

  • 数据在名称/值对中
  • 数据由逗号分隔
  • 大括号 {} 保存对象
  • 中括号 [] 保存数组,数组可以包含多个对象

JSON的值可以是:

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false)
  • 数组(在中括号中)
  • 对象(在大括号中)
  • null

给出一个简单的JSON格式文件示例

{
    "sites": [
        { "name":"菜鸟教程" , "url":"www.runoob.com" }, 
        { "name":"google" , "url":"www.google.com" }, 
        { "name":"微博" , "url":"www.weibo.com" }
    ],
    "flag" : true
}

2. 使用JSONcpp开源库解析JSON文件

2.1 jsoncpp源码下载

直接在github搜索jsoncpp即可。给出下载连接:https://github.com/open-source-parsers/jsoncpp

2.2 具体配置步骤

1> 解压源码

2> 在源码目录的上一层新建build目录,用来保存编译过程生成的中间文件

3> 在build目录执行cmake …

4> 在build目录执行make

5> 在build目录下执行make install

查看安装在本地的jsoncpp库

ls /usr/local/include ls/usr/local/lib

将编译生成的头文件,还有.so文件放在项目中,可以直接使用jsoncpp的库函数。

我这里已经写好了一个示例项目https://github.com/yum9193/json_cpp_usage

3. 关于jsoncpp库的使用简介

使用jsoncpp有两种方法

方法一:使用Jsoncpp生成的lib文件

解压上面下载的Jsoncpp文件,在jsoncpp默认生成静态链接库。 在工程中引用,只需要包含include/json下的头文件及生成的.lib文件即可。

方法二:使用Jsoncpp包中的.cpp和.h文件

解压上面下载的Jsoncpp文件,把jsoncpp-src-0.5.0文件拷贝到工程目录下,将jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\include\json和jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\src\lib_json目录里的文件包含到VS工程中,在VS工程的属性C/C++下General中Additional Include Directories包含头文件目录.\jsoncpp-src-0.5.0\include。在使用的cpp文件中包含json头文件即可,如:#include “json/json.h”。将json_reader.cpp、json_value.cpp和json_writer.cpp三个文件的Precompiled Header属性设置为Not Using Precompiled Headers,否则编译会出现错误。

jsoncpp 使用详解

jsoncpp 主要包含三种类型的 class:Value、Reader、Writer。jsoncpp 中所有对象、类名都在 namespace Json 中,包含 json.h 即可。

Json::Value 只能处理 ANSI 类型的字符串,如果 C++ 程序是用 Unicode 编码的,最好加一个 Adapt 类来适配。

4. 使用c++读取json文件示例

demo.json文件【源码直接抄录自https://blog.csdn.net/shuiyixin/article/details/89330529

{
   "age" : 21,
   "friends" : {
      "friend_age" : 21,
      "friend_name" : "ZhaoWuxian",
      "friend_sex" : "man"
   },
   "hobby" : [ "sing", "run", "Tai Chi" ],
   "name" : "shuiyixin",
   "sex" : "man"
}

test.cpp文件

#include <iostream>
#include <json/json.h>
#include <fstream>
using namespace std;
void readFileJson()
{
        Json::Reader reader;
        Json::Value root;
        //从文件中读取,保证当前文件有demo.json文件  
        ifstream in("demo.json", ios::binary);
        if (!in.is_open())
        {
                cout << "Error opening file\n";
                return;
        }
        if (reader.parse(in, root))
        {
                //读取根节点信息  
                string name = root["name"].asString();
                int age = root["age"].asInt();
                string sex = root["sex"].asString();
                cout << "My name is " << name << endl;
                cout << "I'm " << age << " years old" << endl;
                cout << "I'm a " << sex << endl;
        
        //读取子节点信息  
                string friend_name = root["friends"]["friend_name"].asString();
                int friend_age = root["friends"]["friend_age"].asInt();
                string friend_sex = root["friends"]["friend_sex"].asString();
                cout << "My friend's name is " << friend_name << endl;
                cout << "My friend's sex is "<<friend_sex << endl;
                cout << "My friend is " << friend_age << " years old" << endl;
                //读取数组信息  
                cout << "Here's my hobby:" << endl;
                for (unsigned int i = 0; i < root["hobby"].size(); i++)
                {
                        string ach = root["hobby"][i].asString();
                        cout << ach << '\t';
                }
                cout << endl;
                cout << "Reading Complete!" << endl;
        }
        else
        {
                cout << "parse error\n" << endl;
        }
        in.close();
}
int main(void)
{
        readFileJson();
        return 0;
}

执行结果如下:

5. 使用c++写入json文件示例

test.cpp文件:
#include <iostream>
#include <json/json.h>
#include <fstream>
using namespace std;
void writeFileJson()
{
  //根节点  
  Json::Value root;
 
  //根节点属性  
  root["name"] = Json::Value("shuiyixin");
  root["age"] = Json::Value(21);
  root["sex"] = Json::Value("man");
 
  //子节点  
  Json::Value friends;
 
  //子节点属性  
  friends["friend_name"] = Json::Value("ZhaoWuxian");
  friends["friend_age"] = Json::Value(21);
  friends["friend_sex"] = Json::Value("man");
 
  //子节点挂到根节点上  
  root["friends"] = Json::Value(friends);
 
  //数组形式  
  root["hobby"].append("sing");
  root["hobby"].append("run");
  root["hobby"].append("Tai Chi");
 
  //直接输出  
  //cout << "FastWriter:" << endl;
  //Json::FastWriter fw;
  //cout << fw.write(root) << endl << endl;
 
  //缩进输出  
  cout << "StyledWriter:" << endl;
  Json::StyledWriter sw;
  cout << sw.write(root) << endl << endl;
 
  //输出到文件  
  ofstream os;
  os.open("demo.json", std::ios::out | std::ios::app);
  if (!os.is_open())
    cout << "error:can not find or create the file which named \" demo.json\"." << endl;
  os << sw.write(root);
  os.close();
 
}
int main(void)
{
        writeFileJson();
        return 0;
}

执行结果如下:可以看到已经在目录新建了demo.json文件,并且写入成功

要注意的是:

1.如果要写入的文件不存在,会自动创建该文件;

2.如果文件存在,写入过程不会覆盖文件中原有数据,而是将新数据写在原有数据后面。

6. 解析json样式字符串

在实际项目中更多使用的是从文件解析json,从字符串解析json示例只是为了完整记录。

6.1 简单json样式字符串解析示例

#include <iostream>
#include <json/json.h>
#include <fstream>
using namespace std;
void readStrJson()
{
  //字符串  
  const char* str =
  "{\"name\":\"shuiyixin\",\"age\":\"21\",\"sex\":\"man\"}";
//  "{
//    "name" : "shuiyixin",
//    "age" : "21",
//    "sex" : "man"
//  }";
 
 
  Json::Reader reader;
  Json::Value root;
 
  //从字符串中读取数据  
  if (reader.parse(str, root))
  {
    string name = root["name"].asString();
    int age = root["nomen"].asInt();
    string sex = root["sex"].asString();
    cout << name + "," << age << "," << sex <<  endl;
  }
 
}
int main(void)
{
        readStrJson();
        return 0;
}

执行结果如下:

6.2 复杂json样式字符串解析示例

#include <iostream>
#include <json/json.h>
#include <fstream>
using namespace std;
void readStrProJson()
{
  string strValue = "{\"name\":\"shuiyixin\",\"major\":[{\"AI\":\"MachineLearning\"},{\"AI\":\"DeepLearning\"},{\"AI\":\"ComputerVision\"}]}";
  
  /*
  {
    "name":"shuiyixin",
    "major":[
    {
      "AI":"MachineLearning"
    },
    {
      "AI":"DeepLearning"
    },
    {
      "AI":"ComputerVision"
    }]
  }
  */
  
  
  Json::Reader reader;
  Json::Value value;
  if (reader.parse(strValue, value))
  {
    string out = value["name"].asString();
    cout << out << endl;
    const Json::Value arrayObj = value["major"];
    for (unsigned int i = 0; i < arrayObj.size(); i++)
    {
      out = arrayObj[i]["AI"].asString();
      cout << out<<endl;
    }
  }
}
int main(void)
{
        readStrProJson();
        return 0;
}

执行结果如下:

7. 组装json样式字符串

#include <iostream>
#include <string.h>
using namespace std;
/**
 * 拼接int
 */
std::string  getKeyValue(std::string sKey, int iValue)
{
    char szDoubleQutoes[] = "\"";
    char szColon[] = ":";
    char szValue[50] = { 0 };
    std::string strResult;
    strResult.append("{");
    strResult.append(szDoubleQutoes);
    strResult.append(sKey);
    strResult.append(szDoubleQutoes);
    strResult.append(szColon);
    sprintf(szValue, "%d", iValue);
    strResult.append(szValue);
    strResult.append("}");
    return strResult;
}
/**
 * 拼接float,保留3位
 */
std::string  getKeyValue(std::string sKey, float fValue)
{
    char szDoubleQutoes[] = "\"";
    char szColon[] = ":";
    char szValue[50] = { 0 };
    std::string strResult;
    strResult.append("{");
    strResult.append(szDoubleQutoes);
    strResult.append(sKey);
    strResult.append(szDoubleQutoes);
    strResult.append(szColon);
    sprintf(szValue, "%0.3f", fValue);
    strResult.append(szValue);
    strResult.append("}");
    return strResult;
}
/**
 * 拼接string
 */
std::string  getKeyValue(std::string sKey, std::string sValue)
{
    char szDoubleQutoes[] = "\"";
    char szColon[] = ":";
    std::string strResult;
    strResult.append("{");
    strResult.append(szDoubleQutoes);
    strResult.append(sKey);
    strResult.append(szDoubleQutoes);
    strResult.append(szColon);
    strResult.append(szDoubleQutoes);
    strResult.append(sValue);
    strResult.append(szDoubleQutoes);
    strResult.append("}");
    return strResult;
}
/**
 * 拼接object
 */
std::string  getKeyValueObject(std::string sKey, std::string sObject)
{
    char szDoubleQutoes[] = "\"";
    char szColon[] = ":";
    std::string strResult;
    strResult.append(szDoubleQutoes);
    strResult.append(sKey);
    strResult.append(szDoubleQutoes);
    strResult.append(szColon);
    strResult.append(sObject);
    return strResult;
}
/**
 * 拼接array
 */
std::string  getKeyValueArray(std::string sKey, std::string sArray)
{
    char szDoubleQutoes[] = "\"";
    char szColon[] = ":";
    std::string strResult;
    strResult.append(szDoubleQutoes);
    strResult.append(sKey);
    strResult.append(szDoubleQutoes);
    strResult.append(szColon);
    strResult.append("[");
    strResult.append(sArray);
    strResult.append("]");
    return strResult;
}
struct student
{
  int age;
  char sex[10];
  float score;
};
int main(void)
{
  student s1;
  s1.age = 20; 
  strcpy(s1.sex, "man");
  s1.score = 120.5;
  
  printf("%s\n", getKeyValue("age", s1.age).c_str());
  printf("%s\n", getKeyValue("sex", s1.sex).c_str());
  printf("%s\n", getKeyValue("score", s1.score).c_str());
  
  return 0;
}

编译输出:

参看连接:

https://blog.csdn.net/shuiyixin/article/details/89330529

https://www.cnblogs.com/liaocheng/p/4243731.html

相关文章
|
2月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
170 1
|
2月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
196 1
|
3月前
|
XML JSON 编解码
从JSON到Protobuf,深入序列化方案的选型与原理
序列化是数据跨边界传输的“翻译官”,将结构化数据转为二进制流。JSON可读性强但冗余大,Protobuf高效紧凑、性能优越,成主流选择。不同场景需权衡标准化与定制优化,选最合适方案。
292 3
|
5月前
|
JSON 人工智能 Go
在Golang中序列化JSON字符串的教程
在Golang中,使用`json.Marshal()`可将数据结构序列化为JSON格式。若直接对JSON字符串进行序列化,会因转义字符导致错误。解决方案包括使用`[]byte`或`json.RawMessage()`来避免双引号被转义,从而正确实现JSON的序列化与反序列化。
233 7
|
6月前
|
XML JSON Java
go语言之JSON序列化
本文介绍了Go语言中的JSON序列化与反序列化,其操作与Java类似。需要注意的是,由于Go语言的包管理机制,变量和引入包的首字母需大写,以便其他包引用。示例代码展示了如何将`Student`结构体进行JSON序列化(返回字节数组,需转为字符串)及反序列化。此外,文章还说明了通过tag(如`json`和`xml`)指定序列化变量的重要性,以避免因包间访问限制导致反序列化失败或值为null的问题。
120 0
|
7月前
|
JSON JavaScript 前端开发
Go语言JSON 序列化与反序列化 -《Go语言实战指南》
本文介绍了 Go 语言中使用 `encoding/json` 包实现 JSON 与数据结构之间的转换。内容涵盖序列化(`Marshal`)和反序列化(`Unmarshal`),包括基本示例、结构体字段标签的使用、控制字段行为的标签(如 `omitempty` 和 `-`)、处理 `map` 和切片、嵌套结构体序列化、反序列化未知结构(使用 `map[string]interface{}`)以及 JSON 数组的解析。最后通过表格总结了序列化与反序列化的方法及类型要求,帮助开发者快速掌握 JSON 数据处理技巧。
|
JSON JavaScript 前端开发
Go语言中json序列化的一个小坑,建议多留意一下
在Go语言开发中,JSON因其简洁和广泛的兼容性而常用于数据交换,但其在处理数字类型时存在精度问题。本文探讨了JSON序列化的一些局限性,并介绍了两种替代方案:Go特有的gob二进制协议,以及msgpack,两者都能有效解决类型保持和性能优化的问题。
373 7
|
2月前
|
JSON API 数据格式
淘宝拍立淘按图搜索API系列,json数据返回
淘宝拍立淘按图搜索API系列通过图像识别技术实现商品搜索功能,调用后返回的JSON数据包含商品标题、图片链接、价格、销量、相似度评分等核心字段,支持分页和详细商品信息展示。以下是该API接口返回的JSON数据示例及详细解析:
|
2月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南
|
3月前
|
机器学习/深度学习 JSON 监控
淘宝拍立淘按图搜索与商品详情API的JSON数据返回详解
通过调用taobao.item.get接口,获取商品标题、价格、销量、SKU、图片、属性、促销信息等全量数据。