json学习

一、json简介

JSON是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。

一些合法的json实例(键值对):
{“name":“Jack”,“sex”:“male”}
{“name”:“Jack”,“age”:18,“address”:{“country”:“China”,“City”:“Chendu”}}
{“a”:1,“b”:[1,2,3]}

二、json-c

json支持很多语言,其中json-c库中是嵌入式开发中常用的库。因为很多地方都以json数据交互协议,尤其嵌入式web数据交互时通常会用到json格式,因此如果需要在产品端进行json数据解析,json-c是一个比较不错的选择。

三、json的安装

  • 1、git下载json-c源码,编译安装:
git clone https://github.com/json-c/json-c.git
sh autogen.sh
./configure
make
sudo make install
  • 2、使用apt-get安装(推荐)
sudo apt-get install libjson0-dev libjson0

安装完成后
json相关头文件在:/usr/include/json-c/
json相关库文件在:/usr/lib/x86_64-linux-gnu/

四、json-c API

4.1 json类型

typedef enum json_type {
	json_type_null,
	json_type_boolean,
	json_type_double,
	json_type_int,
	json_type_object,
	json_type_array,
	json_type_string,
} json_type;

4.2 json-c API函数使用

  • 1、将符合json格式的字符串构造成一个json对象
struct json_object *json_token_parse(const char *s);
  • 2、将json对象内容,转成json格式的字符串
const char *json_object_to_json_stritng(struct json_object *obj);
  • 3、创建json对象
struct json_object *json_object_new_object();
  • 4、往json对象中添加键值对
void json_object_object_add(struct json_object *obj, const *key, struct json_object *value);
  • 5、将C字符串转换成json字符串格式的对象
struct json_object *json_object_new_string(const char *s);
  • 6、将整数转换成json格式的对象
struct json_object *json_object_new_int(int32_t i);
  • 7、获取json对象的整形数值
int32_t json_object_get_int(struct json_object *obj);
  • 8、获取json对象的字符串值
const char *json_object_get_string(struct json_object *obj);
  • 9、解析json分为两步

(1)根据键名、从json对象中获取对应数据的json对象

struct json_object *json;
json_object_object_get_ex(obj, "name", &json);

(2)根据数据类型,将数据对应的json对象转换为对应类型的数据

json_type type = json_object_get_type(json);

if (json_type_string == type) {
	printf("name: %s\n", json_object_get_string(json)); //json对象转换为字符串类型
}

json_object_object_get_ex(obj, "age", &json);
printf("age: %d\n", json_object_get_int(json));

json_object_object_get_ex(obj, "sex", &json);
printf("sec: %d\n", json_object_get_string(json));

案例1:

#include <stdio.h>
#include <json-c/json.h>
#include <string.h>


int main(void) {
    const char *str = "{\"name\":\"jack\",\"age\":22,\"sex\":\"male\"}";
    
    // 把符合json格式的字符串转换成json对象
    struct json_object *obj = json_tokener_parse(str);

    // 把json对象转换成字符串输出
    printf("%s\n", json_object_to_json_string(obj));

    return 0;
}

输出结果:
在这里插入图片描述

案例2:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <json-c/json.h>

int main(void) {
    // 创建空json对象
    struct json_object *obj = json_object_new_object();

    // 往json对象里添加键值对
        // json_object_new_sring()把字符串转换成json对象
        // json_object_new_int()把整形数据转换成json对象
    json_object_object_add(obj, "name", json_object_new_string("jack"));
    json_object_object_add(obj, "age", json_object_new_int(24));
    json_object_object_add(obj, "sex", json_object_new_string("male"));

    // 打印json对象
    printf("%s\n", json_object_to_json_string(obj));
    printf("%ld\n", strlen(json_object_to_json_string(obj)));

    // 解析json
    // 第一步:根据键名解析出对应的json对象
    struct json_object *json;
    json_object_object_get_ex(obj, "name", &json);

    // 第二步:根据json对象类型转换成对应的数据
    // 先获取json对象类型
    json_type type = json_object_get_type(json);
    if (json_type_string == type) {
            // json对象转换成字符串对象
        printf("name: %s\n", json_object_get_string(json));
    }

    json_object_object_get_ex(obj, "age", &json);
    printf("age: %d\n", json_object_get_int(json));

    json_object_object_get_ex(obj, "sex", &json);
    printf("sex: %s\n", json_object_get_string(json));

    return 0;
}	

运行结果
在这里插入图片描述
案例3:

#include <stdio.h>
#include <json-c/json.h>

int main(void) {
    struct json_object *obj = json_object_new_object();

    json_object_object_add(obj, "name", json_object_new_string("jack"));

    // 创建json数组对象
    struct json_object *array = json_object_new_array();
    json_object_array_add(array, json_object_new_int(100));
    json_object_array_add(array, json_object_new_int(90));
    json_object_array_add(array, json_object_new_int(80));

    // 把数组对象添加到json对象中
    json_object_object_add(obj, "score", array);

    printf("%s\n", json_object_to_json_string(obj));

    struct json_object *json;
    json_object_object_get_ex(obj, "score", &json);
    if (json_object_get_type(json) == json_type_array) {
        int i;
        // 获取json_type_array类型json对象长度
        int size = json_object_array_length(json);
        for (i = 0; i < size; i++) {
            // 根据下标提取json对象
            struct json_object *j = json_object_array_get_idx(json, i); 
            if (json_type_int == json_object_get_type(j)) {
                            printf("%d\n", json_object_get_int(j));
            }
        }
    }
    return 0;
}

运行结果:
在这里插入图片描述
案例4:json用于服务端-客户端之间发送消息

server

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <json-c/json.h>

int main(void) {
    //第一步:创建socket  
    // socket():地址族:IPV4协议  套接字类型:流式套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == sockfd) {
        perror("socket");
        exit(1);
    }

    // 第二步:绑定信息
    struct sockaddr_in server_info;  // 用于保存服务器的信息(IP PORT)
    bzero(&server_info, sizeof(struct sockaddr_in)); // 清空
    server_info.sin_family = AF_INET; // 地址族
    server_info.sin_port = 7000; // 端口 大于1024都行
    //server_info.sin_addr.s_addr = 127.0.0.1; // 表示回环IP 用于测试
    server_info.sin_addr.s_addr = inet_addr("172.27.194.74");

    if (bind(sockfd, (struct sockaddr *)&server_info,
        sizeof(server_info)) == -1) {
        perror("bind");
        exit(2);
    }

    // 第三步:设置监听队列
    if (listen(sockfd, 10) == -1) {
        perror("listen");
        exit(3);
    }

    printf("等待客户端的连接 ...\n");

    // 第四步:接受连接 (阻塞)
    struct sockaddr_in client_info; // 用于保存客户端的信息
    int length = sizeof(client_info);

    int fd = accept(sockfd, (struct sockaddr *)&client_info, &length);
    if (-1 == fd) {
        perror("accept");
        exit(4);
    }

    printf("接受客户端的连接 %d \n", fd);
    
    // 第五步:读写操作
    char buf[1024] = {0};
    ssize_t size;

    size = recv(fd, buf, sizeof(buf), 0);
    if (-1 == size) {
        perror("recv");
        exit(5);
    }

    // 字符串转换成json
    struct json_object *obj = json_tokener_parse(buf);
    struct json_object *json;

    json_object_object_get_ex(obj, "name", &json);
    printf("name: %s\n", json_object_get_string(json));

    json_object_object_get_ex(obj, "age", &json);
    printf("age: %d\n", json_object_get_int(json));

    json_object_object_get_ex(obj, "sex", &json);
    printf("sex: %s\n", json_object_get_string(json));

    close(fd);  // 关闭TCP连接,不能再接收数据
    close(sockfd); // 关闭socket,不能再处理客户端的请求

    // sockfd用于处理客户端连接  fd用于处理客户端的消息
    return 0;
}       

client

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <json-c/json.h>


int main(void) {
    // 第一步:创建socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (-1 == sockfd) {
        perror("socket");
        exit(1);
    }   

    // 第二步:发起连接
    struct sockaddr_in server_info; // 保存服务器的信息
    bzero(&server_info, sizeof(server_info));
    server_info.sin_family = AF_INET;
    server_info.sin_port = 7000;
    server_info.sin_addr.s_addr = inet_addr("172.27.194.74");

    if (-1 == connect(sockfd, (struct sockaddr *)&server_info, 
            sizeof(server_info))) {
        perror("connect");
        exit(2);
    }

    // 第三步:读写数据
    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "name", json_object_new_string("jack"));
    json_object_object_add(json, "age", json_object_new_int(11));
    json_object_object_add(json, "sex", json_object_new_string("male"));

    const char *buf = json_object_to_json_string(json);

    if (-1 == send(sockfd, buf, strlen(buf), 0)) {
        perror("send");
        exit(3);
    }

    printf("字符串 %s 发送成功 长度 %ld \n", buf,strlen(buf));

    close(sockfd);

    return 0;
}

运行结果
终端1
在这里插入图片描述
终端2
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值