基于cJSON及心知天气模块化实现获取城市气象信息(现在、未来) ...

打印 上一主题 下一主题

主题 844|帖子 844|积分 2532

V1.0 2024年6月14日 发布于博客园

目次

序言

功能描述

用于请求心知天气的信息, 现在的信息, 未来n天的气象信息(免费版仅能3天).
使用域名通过TCP连接到心知天气服务器, 采用cJSON进行解析.
模块化实现, 可选择英文、中文;天数;城市;
运行效果示范
  1. 天气服务器域名 api.seniverse.com 的IP地址是 116.62.81.138
  2. 位置 ID: WS0E9D8WN298
  3. 位置名称: 广州
  4. 国家: CN
  5. 位置: 广州,广州,广东,中国
  6. 时区: Asia/Shanghai
  7. 时区偏移: +08:00
  8. 天气情况: 阴
  9. 天气代码: 9
  10. 温度: 26
  11. 最后更新时间: 2024-06-14T20:52:05+08:00
  12. 城市 ID:         WS0E9D8WN298
  13. 城市名称:        广州
  14. 国家:            CN
  15. 具体位置:        广州,广州,广东,中国
  16. 时区:            Asia/Shanghai
  17. 时区偏移:        +08:00
  18. 日期:                    2024-06-14
  19. 白天天气现象文字:        小雨
  20. 白天天气现象代码:        13
  21. 夜间天气现象文字:        暴雨
  22. 夜间天气现象代码:        16
  23. 当天最高气温:    31
  24. 当天最低气温:    26
  25. 降水量:         19.53
  26. 降水概率:        0.98
  27. 风向文字:        西南
  28. 风向角度:        225
  29. 风速:            8.4
  30. 风力等级:        2
  31. 相对湿度:        91
  32. 日期:                    2024-06-15
  33. 白天天气现象文字:        暴雨
  34. 白天天气现象代码:        16
  35. 夜间天气现象文字:        中雨
  36. 夜间天气现象代码:        14
  37. 当天最高气温:    31
  38. 当天最低气温:    26
  39. 降水量:         28.09
  40. 降水概率:        0.98
  41. 风向文字:        南
  42. 风向角度:        180
  43. 风速:            23.4
  44. 风力等级:        4
  45. 相对湿度:        87
  46. 日期:                    2024-06-16
  47. 白天天气现象文字:        中雨
  48. 白天天气现象代码:        14
  49. 夜间天气现象文字:        雷阵雨
  50. 夜间天气现象代码:        11
  51. 当天最高气温:    32
  52. 当天最低气温:    26
  53. 降水量:         18.96
  54. 降水概率:        0.97
  55. 风向文字:        南
  56. 风向角度:        180
  57. 风速:            15.3
  58. 风力等级:        3
  59. 相对湿度:        87
  60. 数据更新时间:    2024-06-14T08:00:00+08:00
  61. 信阳气象信息
  62. 位置 ID: WT9NG9P4ZDHG
  63. 位置名称: 信阳
  64. 国家: CN
  65. 位置: 信阳,信阳,河南,中国
  66. 时区: Asia/Shanghai
  67. 时区偏移: +08:00
  68. 天气情况: 晴
  69. 天气代码: 1
  70. 温度: 32
  71. 最后更新时间: 2024-06-14T20:48:23+08:00
  72. 城市 ID:         WT9NG9P4ZDHG
  73. 城市名称:        信阳
  74. 国家:            CN
  75. 具体位置:        信阳,信阳,河南,中国
  76. 时区:            Asia/Shanghai
  77. 时区偏移:        +08:00
  78. 日期:                    2024-06-14
  79. 白天天气现象文字:        阴
  80. 白天天气现象代码:        9
  81. 夜间天气现象文字:        晴
  82. 夜间天气现象代码:        1
  83. 当天最高气温:    39
  84. 当天最低气温:    25
  85. 降水量:         0.00
  86. 降水概率:        0.00
  87. 风向文字:        东
  88. 风向角度:        90
  89. 风速:            23.4
  90. 风力等级:        4
  91. 相对湿度:        65
  92. 日期:                    2024-06-15
  93. 白天天气现象文字:        晴
  94. 白天天气现象代码:        0
  95. 夜间天气现象文字:        阴
  96. 夜间天气现象代码:        9
  97. 当天最高气温:    39
  98. 当天最低气温:    27
  99. 降水量:         0.00
  100. 降水概率:        0.00
  101. 风向文字:        北
  102. 风向角度:        0
  103. 风速:            8.4
  104. 风力等级:        2
  105. 相对湿度:        53
  106. 日期:                    2024-06-16
  107. 白天天气现象文字:        小雨
  108. 白天天气现象代码:        13
  109. 夜间天气现象文字:        阴
  110. 夜间天气现象代码:        9
  111. 当天最高气温:    35
  112. 当天最低气温:    25
  113. 降水量:         19.45
  114. 降水概率:        0.99
  115. 风向文字:        东北
  116. 风向角度:        45
  117. 风速:            3.0
  118. 风力等级:        1
  119. 相对湿度:        95
  120. 数据更新时间:    2024-06-14T08:00:00+08:00
复制代码
注意!

在weather_api.h中必要填写自己的私钥
#define KEY "XXXXXXXXX" // 自己的私钥
代码

weather_api.h
  1. #ifndef _WEATHER_API_H
  2. #define _WEATHER_API_H
  3. /**
  4. * @file name : weather_api.h
  5. * @brief     : 用于请求心知天气的信息, 现在的信息, 未来n天的气象信息(免费版仅能3天).
  6. *              使用域名通过TCP连接到心知天气服务器, 采用cJSON进行解析.
  7. *              模块化实现, 可选择英文、中文;天数;城市;
  8. * @author    : RISE_AND_GRIND@163.com
  9. * @date      : 2024年6月14日
  10. * @version   : 1.0
  11. * @note      :
  12. * CopyRight (c)  2023-2024   RISE_AND_GRIND@163.com   All Right Reseverd
  13. */
  14. /***************************************头文件***************************************/
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <netdb.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #include <stdio.h>
  21. #include <errno.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include "cJSON.h"
  26. /***************************************END******************************************/
  27. /***************************************预处理***************************************/
  28. // 目标服务器ip地址 端口号
  29. // #define IPADDR "116.62.81.138"
  30. #define SERVERHOSTNAME "api.seniverse.com" // 服务器域名
  31. #define PORT 80
  32. #define MAX_STRING_LENGTH 100 // 解析到的JSON键值的最大长度
  33. #define BUFFERSIZE 4096       // 缓冲区大小
  34. #define DAYS_COUNT 3          // 要查询的未来几天天气
  35. // 配置信息 访问频限 20次/分钟 国内370个主要城市
  36. #define KEY "XXXXXXXXX" // 自己的私钥
  37. #define LOCAL "guangzhou"       // 解析的城市
  38. #define TYPEINFO 0              // 1默认输出解析到的信息, 0关闭
  39. /**
  40. * 国内 370 个主要城市
  41. * 1 天气实况,包括天气现象文字、代码和气温 3 项数据
  42. * 2 未来 3 天天气预报,包括白天天气现象文字及代码、晚间天气现象文字及代码、当天最高温度和最低温度、风向风速
  43. * 3 6 项基本类生活指数,包括穿衣、紫外线强度、洗车、旅游、感冒、运动指数
  44. */
  45. /***************************************END******************************************/
  46. /***************************************数据类型***************************************/
  47. // 请求的位置信息
  48. typedef struct
  49. {
  50.     char id[MAX_STRING_LENGTH];              // 城市ID
  51.     char name[MAX_STRING_LENGTH];            // 城市名称
  52.     char country[MAX_STRING_LENGTH];         // 国家
  53.     char path[MAX_STRING_LENGTH];            // 具体位置
  54.     char timezone[MAX_STRING_LENGTH];        // 时区
  55.     char timezone_offset[MAX_STRING_LENGTH]; // 时区偏移
  56. } Location;
  57. // 返回指定days天数的结果 定义未来天气结构体 未来15天/24小时  每天更新2次,8点和20点
  58. typedef struct
  59. {
  60.     char date[MAX_STRING_LENGTH];                  // 日期
  61.     char text_day[MAX_STRING_LENGTH];              // 白天天气现象文字:阴晴多云等
  62.     char code_day[MAX_STRING_LENGTH];              // 白天天气现象代码
  63.     char text_night[MAX_STRING_LENGTH];            // 夜间天气现象文字:阴晴多云等
  64.     char code_night[MAX_STRING_LENGTH];            // 夜间天气现象代码
  65.     char high[MAX_STRING_LENGTH];                  // 当天最高气温
  66.     char low[MAX_STRING_LENGTH];                   // 当天最低气温
  67.     char rainfall[MAX_STRING_LENGTH];              // 降水量:当天累计降水量,毫米(mm)
  68.     char precip[MAX_STRING_LENGTH];                // 降水概率,范围0~100,单位百分比(目前仅支持国外城市)
  69.     char wind_direction[MAX_STRING_LENGTH];        // 风向文字:地面10米风向,东、东南、南、西南等
  70.     char wind_direction_degree[MAX_STRING_LENGTH]; // 风向角度,范围0~360, 地面10米风向,东、东南、南、西南等
  71.     char wind_speed[MAX_STRING_LENGTH];            // 风速,单位km/h(当unit=c时)、mph(当unit=f时)
  72.     char wind_scale[MAX_STRING_LENGTH];            // 风力等级:根据风速大小划分的等级
  73.     char humidity[MAX_STRING_LENGTH];              // 相对湿度:地面2米湿度,百分比%
  74. } Daily;
  75. // 天气实况信息
  76. typedef struct
  77. {
  78.     char text[MAX_STRING_LENGTH];        // 天气现象文字
  79.     char code[MAX_STRING_LENGTH];        // 天气现象代码
  80.     char temperature[MAX_STRING_LENGTH]; // 温度,单位为c摄氏度或f华氏度
  81. } Now;
  82. // 天气实况
  83. typedef struct
  84. {
  85.     Location location;                   // 请求的位置信息
  86.     Now now;                             //
  87.     char last_update[MAX_STRING_LENGTH]; // 数据更新时间(该城市的本地时间)
  88. } WeatherResults;
  89. // 未来 3 天天气预报
  90. typedef struct
  91. {
  92.     Location location;                   // 请求的位置信息
  93.     Daily daily[DAYS_COUNT];             // 返回指定days天数的结果
  94.     char last_update[MAX_STRING_LENGTH]; // 数据更新时间(该城市的本地时间)
  95. } WeatherResultsFuture;
  96. /***************************************END******************************************/
  97. /**************************************函数声明**************************************/
  98. /** 解析天气实况JSON信息
  99. * @name      parse_weather
  100. * @brief     解析天气实况JSON信息
  101. * @param     json_data JSON格式的字符串(未解析的格式, 从接收区收到)
  102. * @param     weather_results 接收天气实况解析结果的结构体
  103. * @date      2024年6月14日
  104. * @version   1.0
  105. * @note      使用前提:WeatherResultsFuture weather_results_future;
  106. */
  107. void parse_weather(const char *json_data, WeatherResults *weather_results);
  108. /** 解析未来3天天气JSON信息
  109. * @name      parse_weather_future
  110. * @brief     解析未来3天天气JSON信息
  111. * @param     json_data JSON格式的字符串(未解析的格式, 从接收区收到)
  112. * @param     weather_results_future 接收未来天气解析结果的结构体
  113. * @date      2024年6月14日
  114. * @version   1.0
  115. * @note      使用前提:WeatherResultsFuture weather_results_future;
  116. */
  117. void parse_weather_future(const char *json_data, WeatherResultsFuture *weather_results_future);
  118. /***************************************END******************************************/
  119. // 打印解析后的天气实况信息
  120. void PrintWeatherInfo(WeatherResults const *weather_results);
  121. // 打印解析后的未来3天天气信息
  122. void PrintWeatherFutureInfo(WeatherResultsFuture const *weather_results_future);
  123. /**
  124. * @brief 解析域名得到 IPv4 地址或 IPv6 地址,优先 IPv4
  125. * @param hostname 域名字符串
  126. * @param ipaddr 用于接收结果的字符数组
  127. * @return 解析到 IPv4 地址返回 4,解析到 IPv6 地址返回 6,失败返回 -1
  128. */
  129. int resolve_hostname(const char *hostname, char *ipaddr);
  130. /** 连接天气服务器
  131. * @name      connectServer
  132. * @brief     连接天气服务器
  133. * @param     ipaddr 服务器ip地址
  134. * @param     port 服务器端口
  135. * @param     tcp_socket_fd 网络套接字描述符
  136. * @return    成功 0; 失败-1 (会自动关闭套接字)
  137. * @date      2024年6月14日
  138. * @version   1.0
  139. * @note      前提: int tcp_socket_fd=-1;//创建公用网络套接字描述符
  140. *            注意: 会创建tcp套接字, 不会自动关闭! 需要做错误处理
  141. *            失败会自动关闭套接字文件, 且tcp_socket_fd=-1;
  142. *            成功, 用完记得手动关闭且tcp_socket_fd;
  143. *
  144. */
  145. int connectServer(const char *ipaddr, int port, int *tcp_socket_fd);
  146. /** 请求天气实况信息
  147. * @name      getWeatherInfo
  148. * @brief     请求天气实况信息并解析
  149. * @param     tcp_socket_fd 网络套接字描述符
  150. * @param     local 城市位置拼音 例如 "guangzhou"
  151. * @param     language 接收的语言 例如 "zh-Hans"表示中文  英文:"en"
  152. * @param     weather_results 天气实况接收结解析结果构体
  153. * @date      2024年6月14日
  154. * @version   1.0
  155. * @note      中文:zh-Hans 英文:en
  156. *  使用前提: connectServer(); char recvbuf[BUFFERSIZE]; // 接收缓冲区    WeatherResults weather_results;
  157. */
  158. void getWeatherInfo(int tcp_socket_fd, char const *local, char const *language, char *recvbuf, WeatherResults *weather_results);
  159. /** 请求未来天气JSON信息
  160. * @name      getWeatherFutureInfo
  161. * @brief     请求未来天气JSON信息
  162. * @param     tcp_socket_fd 网络套接字描述符
  163. * @param     local 城市位置拼音 例如 "guangzhou"
  164. * @param     language 接收的语言 例如 "zh-Hans"表示中文  英文:"en"
  165. * @param     weather_results 天气实况接收结解析结果构体
  166. * @date      2024年6月14日
  167. * @version   1.0
  168. * @note      中文:zh-Hans 英文:en
  169. *  使用前提: connectServer(); char recvbuf[BUFFERSIZE]; // 接收缓冲区    WeatherResultsFuture weather_results_future;
  170. */
  171. void getWeatherFutureInfo(int tcp_socket_fd, char const *local, char const *language, char *recvbuf, WeatherResultsFuture *weather_results_future);
  172. #endif //_WEATHER_API_H
复制代码
weather_api.c
  1. /**
  2. * @file name : weather_api.c
  3. * @brief     : 用于请求心知天气的信息, 现在的信息, 未来n天的气象信息(免费版仅能3天).
  4. *              使用域名通过TCP连接到心知天气服务器, 采用cJSON进行解析.
  5. *              模块化实现, 可选择英文、中文;天数;城市;
  6. * @author    : RISE_AND_GRIND@163.com
  7. * @date      : 2024年6月14日
  8. * @version   : 1.0
  9. * @note      :
  10. * CopyRight (c)  2023-2024   RISE_AND_GRIND@163.com   All Right Reseverd
  11. */
  12. #include "weather_api.h"
  13. /** 解析天气实况JSON信息
  14. * @name      parse_weather
  15. * @brief     解析天气实况JSON信息
  16. * @param     json_data JSON格式的字符串(未解析的格式, 从接收区收到)
  17. * @param     weather_results 接收天气实况解析结果的结构体
  18. * @date      2024年6月14日
  19. * @version   1.0
  20. * @note      使用前提:WeatherResultsFuture weather_results_future;
  21. */
  22. void parse_weather(const char *json_data, WeatherResults *weather_results)
  23. {
  24.     //  使用cJSON库解析JSON字符串
  25.     cJSON *json = cJSON_Parse(json_data);
  26.     if (json == NULL)
  27.     {
  28.         fprintf(stderr, "解析天气实况 JSON 错误\n");
  29.         return;
  30.     }
  31. #if TYPEINFO
  32.     // 把解析之后的JSON格式结构体进行输出
  33.     printf("实时天气是\n%s\n", cJSON_Print(json));
  34. #endif
  35.     // 获取JSON对象中的"results"数组
  36.     cJSON *results = cJSON_GetObjectItem(json, "results");
  37.     if (results == NULL || !cJSON_IsArray(results))
  38.     {
  39.         fprintf(stderr, "查找“results”数组时出错\n");
  40.         cJSON_Delete(json);
  41.         return;
  42.     }
  43.     // 获取"results"数组中的第一个元素
  44.     cJSON *result = cJSON_GetArrayItem(results, 0); // 假设数组中只有一个结果
  45.     if (result == NULL)
  46.     {
  47.         fprintf(stderr, "在“results”数组中查找第一项时出错\n");
  48.         cJSON_Delete(json);
  49.         return;
  50.     }
  51.     // 获取"result"对象中的"location"对象
  52.     cJSON *location = cJSON_GetObjectItem(result, "location");
  53.     if (location != NULL)
  54.     {
  55.         // 将"location"对象中的各个字段值复制到weather_results->location结构体中
  56.         strncpy(weather_results->location.id, cJSON_GetObjectItem(location, "id")->valuestring, MAX_STRING_LENGTH);
  57.         strncpy(weather_results->location.name, cJSON_GetObjectItem(location, "name")->valuestring, MAX_STRING_LENGTH);
  58.         strncpy(weather_results->location.country, cJSON_GetObjectItem(location, "country")->valuestring, MAX_STRING_LENGTH);
  59.         strncpy(weather_results->location.path, cJSON_GetObjectItem(location, "path")->valuestring, MAX_STRING_LENGTH);
  60.         strncpy(weather_results->location.timezone, cJSON_GetObjectItem(location, "timezone")->valuestring, MAX_STRING_LENGTH);
  61.         strncpy(weather_results->location.timezone_offset, cJSON_GetObjectItem(location, "timezone_offset")->valuestring, MAX_STRING_LENGTH);
  62.     }
  63.     // 获取"result"对象中的"now"对象
  64.     cJSON *now = cJSON_GetObjectItem(result, "now");
  65.     if (now != NULL)
  66.     {
  67.         // 将"now"对象中的各个字段值复制到weather_results->now结构体中
  68.         strncpy(weather_results->now.text, cJSON_GetObjectItem(now, "text")->valuestring, MAX_STRING_LENGTH);
  69.         strncpy(weather_results->now.code, cJSON_GetObjectItem(now, "code")->valuestring, MAX_STRING_LENGTH);
  70.         strncpy(weather_results->now.temperature, cJSON_GetObjectItem(now, "temperature")->valuestring, MAX_STRING_LENGTH);
  71.     }
  72.     // 将"result"对象中的"last_update"字段值复制到weather_results->last_update字符数组中
  73.     strncpy(weather_results->last_update, cJSON_GetObjectItem(result, "last_update")->valuestring, MAX_STRING_LENGTH);
  74.     // 释放cJSON对象
  75.     cJSON_Delete(json);
  76. }
  77. /** 解析未来n天天气JSON信息
  78. * @name      parse_weather_future
  79. * @brief     解析未来3天天气JSON信息
  80. * @param     json_data JSON格式的字符串(未解析的格式, 从接收区收到)
  81. * @param     weather_results_future 接收未来天气解析结果的结构体
  82. * @date      2024年6月14日
  83. * @version   1.0
  84. * @note      使用前提:WeatherResultsFuture weather_results_future;
  85. */
  86. void parse_weather_future(const char *json_data, WeatherResultsFuture *weather_results_future)
  87. {
  88.     // 使用cJSON库解析JSON字符串
  89.     cJSON *json = cJSON_Parse(json_data);
  90.     if (json == NULL)
  91.     {
  92.         fprintf(stderr, "Error parsing JSON\n");
  93.         return;
  94.     }
  95. #if TYPEINFO
  96.     // 把解析之后的JSON格式结构体进行输出
  97.     printf("未来天气是\n%s\n", cJSON_Print(json));
  98. #endif
  99.     // 获取JSON对象中的"results"数组
  100.     cJSON *results = cJSON_GetObjectItem(json, "results");
  101.     if (results == NULL || !cJSON_IsArray(results))
  102.     {
  103.         fprintf(stderr, "查找“results”数组时出错\n");
  104.         cJSON_Delete(json);
  105.         return;
  106.     }
  107.     // 获取"results"数组中的第一个元素
  108.     cJSON *result = cJSON_GetArrayItem(results, 0); // 假设数组中只有一个结果
  109.     if (result == NULL)
  110.     {
  111.         fprintf(stderr, "在“results”数组中查找第一项时出错\n");
  112.         cJSON_Delete(json);
  113.         return;
  114.     }
  115.     // 获取"result"对象中的"location"对象
  116.     cJSON *location = cJSON_GetObjectItem(result, "location");
  117.     if (location != NULL)
  118.     {
  119.         // 将"location"对象中的各个字段值复制到weather_results_future->location结构体中
  120.         strncpy(weather_results_future->location.id, cJSON_GetObjectItem(location, "id")->valuestring, MAX_STRING_LENGTH);
  121.         strncpy(weather_results_future->location.name, cJSON_GetObjectItem(location, "name")->valuestring, MAX_STRING_LENGTH);
  122.         strncpy(weather_results_future->location.country, cJSON_GetObjectItem(location, "country")->valuestring, MAX_STRING_LENGTH);
  123.         strncpy(weather_results_future->location.path, cJSON_GetObjectItem(location, "path")->valuestring, MAX_STRING_LENGTH);
  124.         strncpy(weather_results_future->location.timezone, cJSON_GetObjectItem(location, "timezone")->valuestring, MAX_STRING_LENGTH);
  125.         strncpy(weather_results_future->location.timezone_offset, cJSON_GetObjectItem(location, "timezone_offset")->valuestring, MAX_STRING_LENGTH);
  126.     }
  127.     // 获取"result"对象中的"daily"数组
  128.     cJSON *daily = cJSON_GetObjectItem(result, "daily");
  129.     if (daily != NULL && cJSON_IsArray(daily))
  130.     {
  131.         // 遍历"daily"数组中的每一天的天气数据
  132.         for (int i = 0; i < DAYS_COUNT; i++)
  133.         {
  134.             cJSON *day = cJSON_GetArrayItem(daily, i);
  135.             if (day != NULL)
  136.             {
  137.                 // 将"day"对象中的各个字段值复制到weather_results_future->daily[i]结构体中
  138.                 strncpy(weather_results_future->daily[i].date, cJSON_GetObjectItem(day, "date")->valuestring, MAX_STRING_LENGTH);
  139.                 strncpy(weather_results_future->daily[i].text_day, cJSON_GetObjectItem(day, "text_day")->valuestring, MAX_STRING_LENGTH);
  140.                 strncpy(weather_results_future->daily[i].code_day, cJSON_GetObjectItem(day, "code_day")->valuestring, MAX_STRING_LENGTH);
  141.                 strncpy(weather_results_future->daily[i].text_night, cJSON_GetObjectItem(day, "text_night")->valuestring, MAX_STRING_LENGTH);
  142.                 strncpy(weather_results_future->daily[i].code_night, cJSON_GetObjectItem(day, "code_night")->valuestring, MAX_STRING_LENGTH);
  143.                 strncpy(weather_results_future->daily[i].high, cJSON_GetObjectItem(day, "high")->valuestring, MAX_STRING_LENGTH);
  144.                 strncpy(weather_results_future->daily[i].low, cJSON_GetObjectItem(day, "low")->valuestring, MAX_STRING_LENGTH);
  145.                 strncpy(weather_results_future->daily[i].rainfall, cJSON_GetObjectItem(day, "rainfall")->valuestring, MAX_STRING_LENGTH);
  146.                 strncpy(weather_results_future->daily[i].precip, cJSON_GetObjectItem(day, "precip")->valuestring, MAX_STRING_LENGTH);
  147.                 strncpy(weather_results_future->daily[i].wind_direction, cJSON_GetObjectItem(day, "wind_direction")->valuestring, MAX_STRING_LENGTH);
  148.                 strncpy(weather_results_future->daily[i].wind_direction_degree, cJSON_GetObjectItem(day, "wind_direction_degree")->valuestring, MAX_STRING_LENGTH);
  149.                 strncpy(weather_results_future->daily[i].wind_speed, cJSON_GetObjectItem(day, "wind_speed")->valuestring, MAX_STRING_LENGTH);
  150.                 strncpy(weather_results_future->daily[i].wind_scale, cJSON_GetObjectItem(day, "wind_scale")->valuestring, MAX_STRING_LENGTH);
  151.                 strncpy(weather_results_future->daily[i].humidity, cJSON_GetObjectItem(day, "humidity")->valuestring, MAX_STRING_LENGTH);
  152.             }
  153.         }
  154.     }
  155.     // 将"result"对象中的"last_update"字段值复制到weather_results_future->last_update字符数组中
  156.     strncpy(weather_results_future->last_update, cJSON_GetObjectItem(result, "last_update")->valuestring, MAX_STRING_LENGTH);
  157.     // 释放cJSON对象
  158.     cJSON_Delete(json);
  159. }
  160. // 打印解析后的天气实况信息
  161. void PrintWeatherInfo(WeatherResults const *weather_results)
  162. {
  163.     // 打印解析后的结构体内容
  164.     printf("\n");
  165.     printf("位置 ID: %s\n", weather_results->location.id);
  166.     printf("位置名称: %s\n", weather_results->location.name);
  167.     printf("国家: %s\n", weather_results->location.country);
  168.     printf("位置: %s\n", weather_results->location.path);
  169.     printf("时区: %s\n", weather_results->location.timezone);
  170.     printf("时区偏移: %s\n", weather_results->location.timezone_offset);
  171.     printf("天气情况: %s\n", weather_results->now.text);
  172.     printf("天气代码: %s\n", weather_results->now.code);
  173.     printf("温度: %s\n", weather_results->now.temperature);
  174.     printf("最后更新时间: %s\n", weather_results->last_update);
  175.     printf("\n");
  176. }
  177. // 打印解析后的未来3天天气信息
  178. void PrintWeatherFutureInfo(WeatherResultsFuture const *weather_results_future)
  179. {
  180.     // 打印解析后的结构体内容
  181.     printf("\n");
  182.     printf("城市 ID:\t %s\n", weather_results_future->location.id);
  183.     printf("城市名称:\t %s\n", weather_results_future->location.name);
  184.     printf("国家:\t\t %s\n", weather_results_future->location.country);
  185.     printf("具体位置:\t %s\n", weather_results_future->location.path);
  186.     printf("时区:\t\t %s\n", weather_results_future->location.timezone);
  187.     printf("时区偏移:\t %s\n", weather_results_future->location.timezone_offset);
  188.     for (int i = 0; i < DAYS_COUNT; i++)
  189.     {
  190.         printf("\n");
  191.         printf("日期:\t\t\t %s\n", weather_results_future->daily[i].date);
  192.         printf("白天天气现象文字:\t %s\n", weather_results_future->daily[i].text_day);
  193.         printf("白天天气现象代码:\t %s\n", weather_results_future->daily[i].code_day);
  194.         printf("夜间天气现象文字:\t %s\n", weather_results_future->daily[i].text_night);
  195.         printf("夜间天气现象代码:\t %s\n", weather_results_future->daily[i].code_night);
  196.         printf("当天最高气温:\t %s\n", weather_results_future->daily[i].high);
  197.         printf("当天最低气温:\t %s\n", weather_results_future->daily[i].low);
  198.         printf("降水量:\t %s\n", weather_results_future->daily[i].rainfall);
  199.         printf("降水概率:\t %s\n", weather_results_future->daily[i].precip);
  200.         printf("风向文字:\t %s\n", weather_results_future->daily[i].wind_direction);
  201.         printf("风向角度:\t %s\n", weather_results_future->daily[i].wind_direction_degree);
  202.         printf("风速:\t\t %s\n", weather_results_future->daily[i].wind_speed);
  203.         printf("风力等级:\t %s\n", weather_results_future->daily[i].wind_scale);
  204.         printf("相对湿度:\t %s\n", weather_results_future->daily[i].humidity);
  205.     }
  206.     printf("数据更新时间:\t %s\n", weather_results_future->last_update);
  207.     printf("\n");
  208. }
  209. /** 解析域名得到 IPv4 地址或 IPv6 地址
  210. * @brief 解析域名得到 IPv4 地址或 IPv6 地址,优先 IPv4
  211. * @param hostname 域名字符串
  212. * @param ipaddr 用于接收结果的字符数组
  213. * @return 解析到 IPv4 地址返回 4,解析到 IPv6 地址返回 6,失败返回 -1
  214. */
  215. int resolve_hostname(const char *hostname, char *ipaddr)
  216. {
  217.     // 定义 addrinfo 结构体变量,用于存储地址信息
  218.     struct addrinfo hints, *res, *p;
  219.     int errcode; // 存储 getaddrinfo 函数的返回值
  220.     void *ptr;   // 指向 IP 地址的指针
  221.     // 清空 hints 结构体并设置相关参数
  222.     memset(&hints, 0, sizeof(hints));
  223.     hints.ai_family = AF_UNSPEC;     // 不指定 IPv4 或 IPv6
  224.     hints.ai_socktype = SOCK_STREAM; // TCP 流套接字
  225.     // 调用 getaddrinfo 函数获取主机名对应的地址信息
  226.     errcode = getaddrinfo(hostname, NULL, &hints, &res);
  227.     if (errcode != 0)
  228.     {
  229.         // 如果 getaddrinfo 返回非零值,则表示出错,打印错误信息并返回 -1
  230.         fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(errcode));
  231.         return -1;
  232.     }
  233.     // 遍历返回的地址信息链表
  234.     for (p = res; p != NULL; p = p->ai_next)
  235.     {
  236.         // 判断地址族是否为 IPv4
  237.         if (p->ai_family == AF_INET)
  238.         {
  239.             // 将 IPv4 地址赋给 ptr
  240.             ptr = &((struct sockaddr_in *)p->ai_addr)->sin_addr;
  241.             // 将地址转换为字符串形式,并存储在 ipaddr 中
  242.             inet_ntop(p->ai_family, ptr, ipaddr, INET6_ADDRSTRLEN);
  243.             freeaddrinfo(res); // 释放 getaddrinfo 分配的内存
  244.             return 4;          // 返回 4 表示解析到 IPv4 地址
  245.         }
  246.     }
  247.     // 如果没有找到 IPv4 地址,继续寻找 IPv6 地址
  248.     for (p = res; p != NULL; p = p->ai_next)
  249.     {
  250.         // 判断地址族是否为 IPv6
  251.         if (p->ai_family == AF_INET6)
  252.         {
  253.             // 将 IPv6 地址赋给 ptr
  254.             ptr = &((struct sockaddr_in6 *)p->ai_addr)->sin6_addr;
  255.             // 将地址转换为字符串形式,并存储在 ipaddr 中
  256.             inet_ntop(p->ai_family, ptr, ipaddr, INET6_ADDRSTRLEN);
  257.             freeaddrinfo(res); // 释放 getaddrinfo 分配的内存
  258.             return 6;          // 返回 6 表示解析到 IPv6 地址
  259.         }
  260.     }
  261.     // 如果没有找到任何地址,释放 getaddrinfo 分配的内存并返回 -1
  262.     freeaddrinfo(res);
  263.     return -1;
  264. }
  265. /** 连接天气服务器
  266. * @name      connectServer
  267. * @brief     连接天气服务器
  268. * @param     ipaddr 服务器ip地址
  269. * @param     port 服务器端口
  270. * @param     tcp_socket_fd 网络套接字描述符
  271. * @return    成功 0; 失败-1 (会自动关闭套接字)
  272. * @date      2024年6月14日
  273. * @version   1.0
  274. * @note      前提: int tcp_socket_fd=-1;//创建公用网络套接字描述符
  275. *            注意: 会创建tcp套接字, 不会自动关闭! 需要做错误处理
  276. *            失败会自动关闭套接字文件, 且tcp_socket_fd=-1;
  277. *            成功, 用完记得手动关闭且tcp_socket_fd;
  278. *
  279. */
  280. int connectServer(const char *ipaddr, int port, int *tcp_socket_fd)
  281. {
  282.     /**********************1.创建TCP套接字**********************/
  283.     *tcp_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  284.     if (*tcp_socket_fd == -1)
  285.     {
  286.         fprintf(stderr, "创建TCP套接字错误, errno:%d,%s\n", errno, strerror(errno));
  287.         exit(1);
  288.     }
  289.     /******************2.发起连接请求,等待接受服务器接受连接 建立TCP连接*******************/
  290.     struct sockaddr_in dest_addr;
  291.     dest_addr.sin_family = AF_INET;                // 协议族,是固定的
  292.     dest_addr.sin_port = htons(PORT);              // 服务器端口,必须转换为网络字节序
  293.                                                    // dest_addr.sin_addr.s_addr = inet_addr(IPADDR); // 服务器地址
  294.     dest_addr.sin_addr.s_addr = inet_addr(ipaddr); // 服务器地址
  295.     /******************3. 客户端连接成功*******************************/
  296.     int ret = connect(*tcp_socket_fd, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
  297.     if (ret < 0)
  298.     {
  299.         fprintf(stderr, "客户端连接失败, errno:%d,%s\n", errno, strerror(errno));
  300.         close(*tcp_socket_fd);
  301.         printf("TCP套接字已经关闭!\n");
  302.         *tcp_socket_fd = -1; // 恢复失败的情况
  303.         return -1;
  304.     }
  305.     return 0;
  306. }
  307. /** 请求天气实况信息
  308. * @name      getWeatherInfo
  309. * @brief     请求天气实况信息并解析
  310. * @param     tcp_socket_fd 网络套接字描述符
  311. * @param     local 城市位置拼音 例如 "guangzhou"
  312. * @param     language 接收的语言 例如 "zh-Hans"表示中文  英文:"en"
  313. * @param     weather_results 天气实况接收结解析结果构体
  314. * @date      2024年6月14日
  315. * @version   1.0
  316. * @note      中文:zh-Hans 英文:en
  317. *  使用前提: connectServer(); char recvbuf[BUFFERSIZE]; // 接收缓冲区    WeatherResults weather_results;
  318. */
  319. void getWeatherInfo(int tcp_socket_fd, char const *local, char const *language, char *recvbuf, WeatherResults *weather_results)
  320. {
  321.     /**************************4. 构建实时天气HTTP请求内容****************************************/
  322.     // 用于存储HTTP的请求内容: 请求行 + 请求字段 + \r\n + 请求包体(可选)
  323.     char reqbuf[1024] = {0}; // 储存http请求内容临时缓存区
  324.     sprintf(reqbuf, "GET https://api.seniverse.com/v3/weather/now.json?key=%s&location=%s&language=%s&unit=c "
  325.                     "HTTP/1.1"
  326.                     "\r\n"
  327.                     "Host:api.seniverse.com\r\n"
  328.                     "\r\n",
  329.             KEY, local, language);
  330.     /**************************5. 发送http请求内容****************************************/
  331.     // 双方建立连接,此时可以利用HTTP协议发送请求信息,并等待服务器的响应  基于请求/响应
  332.     send(tcp_socket_fd, reqbuf, strlen(reqbuf), 0);
  333.     /**************************6. 等待服务器的响应****************************************/
  334.     /*************请求实时天气**************** */
  335.     bzero(recvbuf, BUFFERSIZE); // 清除缓冲区
  336.     // 第一次返回的响应参数
  337.     recv(tcp_socket_fd, recvbuf, BUFFERSIZE, 0); // 从TCP套接字接收数据
  338. #if TYPEINFO
  339.     printf("%s\n", recvbuf); // 打印接收到的响应参数
  340. #endif
  341.     bzero(recvbuf, BUFFERSIZE);
  342.     // 第二次返回的响应包体
  343.     recv(tcp_socket_fd, recvbuf, BUFFERSIZE, 0);
  344. #if TYPEINFO
  345.     printf("%s\n", recvbuf); // 打印接收到的响应包体
  346. #endif
  347.     /*************解析实时天气**************** */
  348.     parse_weather(recvbuf, weather_results); // 调用解析函数,解析接收到的JSON数据并填充结构体
  349.     // 打印解析后的结构体内容
  350.     PrintWeatherInfo(weather_results);
  351. }
  352. /** 请求未来天气JSON信息
  353. * @name      getWeatherFutureInfo
  354. * @brief     请求未来天气JSON信息
  355. * @param     tcp_socket_fd 网络套接字描述符
  356. * @param     local 城市位置拼音 例如 "guangzhou"
  357. * @param     language 接收的语言 例如 "zh-Hans"表示中文  英文:"en"
  358. * @param     weather_results 天气实况接收结解析结果构体
  359. * @date      2024年6月14日
  360. * @version   1.0
  361. * @note      中文:zh-Hans 英文:en
  362. *  使用前提: connectServer(); char recvbuf[BUFFERSIZE]; // 接收缓冲区    WeatherResultsFuture weather_results_future;
  363. */
  364. void getWeatherFutureInfo(int tcp_socket_fd, char const *local, char const *language, char *recvbuf, WeatherResultsFuture *weather_results_future)
  365. {
  366.     /*********************************请求未来2天天气************************************** */
  367.     /**************************4. 构建未来天气HTTP请求内容****************************************/
  368.     // 用于存储HTTP的请求内容: 请求行 + 请求字段 + \r\n + 请求包体(可选)
  369.     char reqbuf[1024] = {0}; // 储存http请求内容临时缓存区
  370.     sprintf(reqbuf, "GET https://api.seniverse.com/v3/weather/daily.json?key=%s&location=%s&language=%s&unit=c&start=0&days=%d "
  371.                     "HTTP/1.1"
  372.                     "\r\n"
  373.                     "Host:api.seniverse.com\r\n"
  374.                     "\r\n",
  375.             KEY, local, language, DAYS_COUNT);
  376.     /**************************5. 发送http请求内容****************************************/
  377.     // 双方建立连接,此时可以利用HTTP协议发送请求信息,并等待服务器的响应  基于请求/响应
  378.     send(tcp_socket_fd, reqbuf, strlen(reqbuf), 0);
  379.     /**************************6. 等待服务器的响应****************************************/
  380.     /*************请求实时天气**************** */
  381.     bzero(recvbuf, BUFFERSIZE); // 清空接收缓冲区
  382.     // 第一次返回的响应参数
  383.     recv(tcp_socket_fd, recvbuf, BUFFERSIZE, 0); // 从TCP套接字接收数据
  384. #if TYPEINFO
  385.     printf("%s\n", recvbuf); // 打印接收到的响应参数
  386. #endif                       // 打印接收到的数据
  387.     bzero(recvbuf, BUFFERSIZE);
  388.     // 第二次返回的响应包体
  389.     recv(tcp_socket_fd, recvbuf, BUFFERSIZE, 0);
  390. #if TYPEINFO
  391.     printf("%s\n", recvbuf); // 打印接收到的响应包体
  392. #endif
  393.     /*************解析未来天气**************** */
  394.     parse_weather_future(recvbuf, weather_results_future); // 调用解析函数,解析接收到的JSON数据并填充结构体
  395.     // 打印解析后的结构体内容
  396.     PrintWeatherFutureInfo(weather_results_future);
  397. }
  398. // 使用示范
  399. #if 0
  400. #include <stdio.h>
  401. #include "cJSON.h"
  402. #include "weather_api.h"
  403. int main(int argc, char const *argv[])
  404. {
  405.     /***********域名解析****************/
  406.     char ipaddr[64] = {0};
  407.     if (resolve_hostname(SERVERHOSTNAME, ipaddr) != -1)
  408.     {
  409.         printf("天气服务器域名 %s 的IP地址是 %s\n", SERVERHOSTNAME, ipaddr);
  410.     }
  411.     else
  412.     {
  413.         printf(" %s 解析域名失败\n", SERVERHOSTNAME);
  414.     }
  415.     // TCP连接服务器
  416.     int tcp_socket_fd = -1;
  417.     if (connectServer(ipaddr, PORT, &tcp_socket_fd) != 0)
  418.     {
  419.         perror("连接天气服务器失败");
  420.         return -1;
  421.     }
  422.     /**************************请求实时天气HTTP请求****************************************/
  423.     char recvbuf[BUFFERSIZE]; // 接收缓冲区
  424.     WeatherResults weather_results;
  425.     getWeatherInfo(tcp_socket_fd, LOCAL, "zh-Hans", recvbuf, &weather_results);
  426.     WeatherResultsFuture weather_results_future;
  427.     getWeatherFutureInfo(tcp_socket_fd, LOCAL, "zh-Hans", recvbuf, &weather_results_future);
  428.     printf("\n信阳气象信息\n");
  429.     getWeatherInfo(tcp_socket_fd, "xinyang", "zh-Hans", recvbuf, &weather_results);
  430.     getWeatherFutureInfo(tcp_socket_fd, "xinyang", "zh-Hans", recvbuf, &weather_results_future);
  431.     close(tcp_socket_fd);
  432.     return 0;
  433. }
  434. #endif
复制代码
demo.c

下面是使用示范
  1. #include <stdio.h>
  2. #include "weather_api.h"
  3. int main(int argc, char const *argv[])
  4. {
  5.     /***********域名解析****************/
  6.     char ipaddr[64] = {0};
  7.     if (resolve_hostname(SERVERHOSTNAME, ipaddr) != -1)
  8.     {
  9.         printf("天气服务器域名 %s 的IP地址是 %s\n", SERVERHOSTNAME, ipaddr);
  10.     }
  11.     else
  12.     {
  13.         printf(" %s 解析域名失败\n", SERVERHOSTNAME);
  14.     }
  15.     // TCP连接服务器
  16.     int tcp_socket_fd = -1;
  17.     if (connectServer(ipaddr, PORT, &tcp_socket_fd) != 0)
  18.     {
  19.         perror("连接天气服务器失败");
  20.         return -1;
  21.     }
  22.     /**************************请求实时天气HTTP请求****************************************/
  23.     char recvbuf[BUFFERSIZE]; // 接收缓冲区
  24.     WeatherResults weather_results;
  25.     getWeatherInfo(tcp_socket_fd, LOCAL, "zh-Hans", recvbuf, &weather_results);
  26.     WeatherResultsFuture weather_results_future;
  27.     getWeatherFutureInfo(tcp_socket_fd, LOCAL, "zh-Hans", recvbuf, &weather_results_future);
  28.     printf("\n信阳气象信息\n");
  29.     getWeatherInfo(tcp_socket_fd, "xinyang", "zh-Hans", recvbuf, &weather_results);
  30.     getWeatherFutureInfo(tcp_socket_fd, "xinyang", "zh-Hans", recvbuf, &weather_results_future);
  31.     close(tcp_socket_fd);
  32.     return 0;
  33. }
复制代码
cJSON.h

下面是我汉化过的cJSON.h
  1. // clang-format off
  2. /*
  3.   Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
  4.   Permission is hereby granted, free of charge, to any person obtaining a copy
  5.   of this software and associated documentation files (the "Software"), to deal
  6.   in the Software without restriction, including without limitation the rights
  7.   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8.   copies of the Software, and to permit persons to whom the Software is
  9.   furnished to do so, subject to the following conditions:
  10.   The above copyright notice and this permission notice shall be included in
  11.   all copies or substantial portions of the Software.
  12.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18.   THE SOFTWARE.
  19. */
  20. /*
  21.   版权所有 (c) 2009-2017 Dave Gamble 和 cJSON 贡献者
  22.   特此免费授予任何获得本软件及相关文档文件(“软件”)副本的个人,不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本,并允许向其提供本软件的人员这样做,须符合以下条件:
  23.   上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。
  24.   本软件按“原样”提供,不提供任何形式的明示或暗示担保,包括但不限于适销性、适用性和非侵权的担保。在任何情况下,作者或版权持有人均不对因本软件或本软件的使用或其他交易引起的任何索赔、损害或其他责任承担责任,无论是在合同诉讼中、侵权行为中还是其他方面。
  25. */
  26. #ifndef cJSON__h
  27. #define cJSON__h
  28. #ifdef __cplusplus
  29. extern "C"
  30. {
  31. #endif
  32. #if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
  33. #define __WINDOWS__
  34. #endif
  35. #ifdef __WINDOWS__
  36.   /* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 3 define options:
  37.   CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
  38.   CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
  39.   CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
  40.   For *nix builds that support visibility attribute, you can define similar behavior by
  41.   setting default visibility to hidden by adding
  42.   -fvisibility=hidden (for gcc)
  43.   or
  44.   -xldscope=hidden (for sun cc)
  45.   to CFLAGS
  46.   then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
  47.   */
  48.   /* 在为 Windows 编译时,我们指定一个特定的调用约定,以避免在从具有不同默认调用约定的项目中调用时出现问题。对于 Windows,有 3 个定义选项:
  49.   CJSON_HIDE_SYMBOLS - 在不希望导出符号时定义
  50.   CJSON_EXPORT_SYMBOLS - 在库构建时定义以导出符号(默认)
  51.   CJSON_IMPORT_SYMBOLS - 在希望导入符号时定义
  52.   对于支持可见性属性的 *nix 构建,您可以通过以下方式定义类似的行为:
  53.   通过添加 -fvisibility=hidden(对于 gcc)或 -xldscope=hidden(对于 sun cc)到 CFLAGS 来设置默认可见性为隐藏
  54.   然后使用 CJSON_API_VISIBILITY 标志以与 CJSON_EXPORT_SYMBOLS 相同的方式“导出”相同的符号
  55.   */
  56. #define CJSON_CDECL __cdecl
  57. #define CJSON_STDCALL __stdcall
  58. /* export symbols by default, this is necessary for copy pasting the C and header file */
  59. /* 默认导出符号,这是复制粘贴 C 和头文件所必需的 */
  60. #if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
  61. #define CJSON_EXPORT_SYMBOLS
  62. #endif
  63. #if defined(CJSON_HIDE_SYMBOLS)
  64. #define CJSON_PUBLIC(type) type CJSON_STDCALL
  65. #elif defined(CJSON_EXPORT_SYMBOLS)
  66. #define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
  67. #elif defined(CJSON_IMPORT_SYMBOLS)
  68. #define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
  69. #endif
  70. #else /* !__WINDOWS__ */
  71. #define CJSON_CDECL
  72. #define CJSON_STDCALL
  73. #if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
  74. #define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
  75. #else
  76. #define CJSON_PUBLIC(type) type
  77. #endif
  78. #endif
  79. /* project version */
  80. /* 项目版本 */
  81. #define CJSON_VERSION_MAJOR 1
  82. #define CJSON_VERSION_MINOR 7
  83. #define CJSON_VERSION_PATCH 18
  84. #include <stddef.h>
  85. /* cJSON Types: */
  86. /* cJSON 类型: */
  87. #define cJSON_Invalid (0)
  88. #define cJSON_False (1 << 0)
  89. #define cJSON_True (1 << 1)
  90. #define cJSON_NULL (1 << 2)
  91. #define cJSON_Number (1 << 3)
  92. #define cJSON_String (1 << 4)
  93. #define cJSON_Array (1 << 5)
  94. #define cJSON_Object (1 << 6)
  95. #define cJSON_Raw (1 << 7) /* raw json */ /* 原始 JSON */
  96. #define cJSON_IsReference 256
  97. #define cJSON_StringIsConst 512
  98.   /* The cJSON structure: */
  99.   /* cJSON 结构体定义: */
  100.   typedef struct cJSON
  101.   {
  102.     /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
  103.     /* next/prev 允许您遍历数组/对象链。或者,使用 GetArraySize/GetArrayItem/GetObjectItem */
  104.     struct cJSON *next;
  105.     struct cJSON *prev;
  106.     /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
  107.     /* 数组或对象项将具有指向数组/对象中项链的子指针。 */
  108.     struct cJSON *child;
  109.     /* The type of the item, as above. */
  110.     /* 项目的类型,如上所述。 */
  111.     int type;
  112.     /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
  113.     /* 项目的字符串,如果 type==cJSON_String 和 type == cJSON_Raw */
  114.     char *valuestring;
  115.     /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
  116.     /* 写入 valueint 已弃用,请改用 cJSON_SetNumberValue */
  117.     int valueint;
  118.     /* The item's number, if type==cJSON_Number */
  119.     /* 项目的数字,如果 type==cJSON_Number */
  120.     double valuedouble;
  121.     /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
  122.     /* 项目的名称字符串,如果该项目是对象的子项或在对象的子项列表中。 */
  123.     char *string;
  124.   } cJSON;
  125.   /* cJSON 钩子函数结构体 */
  126.   typedef struct cJSON_Hooks
  127.   {
  128.     /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
  129.     /* malloc/free 在 Windows 上是 CDECL,无论编译器的默认调用约定如何,因此确保钩子允许直接传递这些函数。 */
  130.     void *(CJSON_CDECL *malloc_fn)(size_t sz);
  131.     void(CJSON_CDECL *free_fn)(void *ptr);
  132.   } cJSON_Hooks;
  133.   typedef int cJSON_bool;
  134.   /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
  135.    * This is to prevent stack overflows. */
  136.   /* 限制数组/对象嵌套的深度,超过此深度 cJSON 将拒绝解析。防止堆栈溢出。 */
  137. #ifndef CJSON_NESTING_LIMIT
  138. #define CJSON_NESTING_LIMIT 1000
  139. #endif
  140.   /* returns the version of cJSON as a string */
  141.   /**
  142.    * @name      cJSON_Version
  143.    * @brief     返回 cJSON 版本号的字符串
  144.    * @return    const char* 版本号字符串
  145.    */
  146.   CJSON_PUBLIC(const char *)  cJSON_Version(void);
  147.   /* Supply malloc, realloc and free functions to cJSON */
  148.   /**
  149.    * @name      cJSON_InitHooks
  150.    * @brief     提供 malloc、realloc 和 free 函数给 cJSON 使用
  151.    * @param     hooks cJSON_Hooks 结构体指针,包含自定义的 malloc 和 free 函数
  152.    */
  153.   CJSON_PUBLIC(void)  cJSON_InitHooks(cJSON_Hooks *hooks);
  154.   /* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
  155.   /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
  156.   /**
  157.    * @name      cJSON_Parse
  158.    * @brief     解析 JSON 字符串并返回 cJSON 对象
  159.    * @param     value JSON 字符串
  160.    * @return    cJSON* 解析后的 cJSON 对象
  161.    * @note      调用者负责释放返回的 cJSON 对象(使用 cJSON_Delete)
  162.    */
  163.   CJSON_PUBLIC(cJSON *)  cJSON_Parse(const char *value);
  164.   /**
  165.    * @name      cJSON_ParseWithLength
  166.    * @brief     解析指定长度的 JSON 字符串并返回 cJSON 对象
  167.    * @param     value JSON 字符串
  168.    * @param     buffer_length 字符串长度
  169.    * @return    cJSON* 解析后的 cJSON 对象
  170.    * @note      调用者负责释放返回的 cJSON 对象(使用 cJSON_Delete)
  171.    */
  172.   CJSON_PUBLIC(cJSON *)  cJSON_ParseWithLength(const char *value, size_t buffer_length);
  173.   /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
  174.   /* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
  175.   /**
  176.    * @name      cJSON_ParseWithOpts
  177.    * @brief     解析 JSON 字符串并返回 cJSON 对象,允许指定是否要求 JSON 以 null 结尾,并检索解析结束的指针
  178.    * @param     value JSON 字符串
  179.    * @param     return_parse_end 解析结束的指针
  180.    * @param     require_null_terminated 是否要求 JSON 以 null 结尾
  181.    * @return    cJSON* 解析后的 cJSON 对象
  182.    * @note      调用者负责释放返回的 cJSON 对象(使用 cJSON_Delete)
  183.    */
  184.   CJSON_PUBLIC(cJSON *)  cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
  185.   /**
  186.    * @name      cJSON_ParseWithLengthOpts
  187.    * @brief     解析指定长度的 JSON 字符串并返回 cJSON 对象,允许指定是否要求 JSON 以 null 结尾,并检索解析结束的指针
  188.    * @param     value JSON 字符串
  189.    * @param     buffer_length 字符串长度
  190.    * @param     return_parse_end 解析结束的指针
  191.    * @param     require_null_terminated 是否要求 JSON 以 null 结尾
  192.    * @return    cJSON* 解析后的 cJSON 对象
  193.    * @note      调用者负责释放返回的 cJSON 对象(使用 cJSON_Delete)
  194.    */
  195.   CJSON_PUBLIC(cJSON *)  cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
  196.   /* Render a cJSON entity to text for transfer/storage. */
  197.   /**
  198.    * @name      cJSON_Print
  199.    * @brief     将 cJSON 对象渲染为文本(带格式)
  200.    * @param     item cJSON 对象
  201.    * @return    char* 渲染后的文本
  202.    * @note      调用者负责释放返回的字符串(使用 stdlib free、cJSON_Hooks.free_fn 或 cJSON_free)
  203.    */
  204.   CJSON_PUBLIC(char *)  cJSON_Print(const cJSON *item);
  205.   /* Render a cJSON entity to text for transfer/storage without any formatting. */
  206.   /**
  207.    * @name      cJSON_PrintUnformatted
  208.    * @brief     将 cJSON 对象渲染为文本(无格式)
  209.    * @param     item cJSON 对象
  210.    * @return    char* 渲染后的文本
  211.    * @note      调用者负责释放返回的字符串(使用 stdlib free、cJSON_Hooks.free_fn 或 cJSON_free)
  212.    */
  213.   CJSON_PUBLIC(char *)  cJSON_PrintUnformatted(const cJSON *item);
  214.   /* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
  215.   /**
  216.    * @name      cJSON_PrintBuffered
  217.    * @brief     使用缓冲策略将 cJSON 对象渲染为文本
  218.    * @param     item cJSON 对象
  219.    * @param     prebuffer 预缓冲大小
  220.    * @param     fmt 是否格式化输出
  221.    * @return    char* 渲染后的文本
  222.    * @note      调用者负责释放返回的字符串(使用 stdlib free、cJSON_Hooks.free_fn 或 cJSON_free)
  223.    */
  224.   CJSON_PUBLIC(char *)  cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
  225.   /* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
  226.   /* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
  227.   /**
  228.    * @name      cJSON_PrintPreallocated
  229.    * @brief     使用已分配的缓冲区将 cJSON 对象渲染为文本
  230.    * @param     item cJSON 对象
  231.    * @param     buffer 已分配的缓冲区
  232.    * @param     length 缓冲区长度
  233.    * @param     format 是否格式化输出
  234.    * @return    cJSON_bool 成功返回 1,失败返回 0
  235.    * @note      调用者对缓冲区完全负责
  236.    */
  237.   CJSON_PUBLIC(cJSON_bool)  cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
  238.   /* Delete a cJSON entity and all subentities. */
  239.   /**
  240.    * @name      cJSON_Delete
  241.    * @brief     删除 cJSON 对象及其所有子对象
  242.    * @param     item cJSON 对象
  243.    */
  244.   CJSON_PUBLIC(void)  cJSON_Delete(cJSON *item);
  245.   /* Returns the number of items in an array (or object). */
  246.   /**
  247.    * @name      cJSON_GetArraySize
  248.    * @brief     返回数组(或对象)中的项数
  249.    * @param     array cJSON 数组
  250.    * @return    int 数组中的项数
  251.    */
  252.   CJSON_PUBLIC(int)  cJSON_GetArraySize(const cJSON *array);
  253.   /* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
  254.   /**
  255.    * @name      cJSON_GetArrayItem
  256.    * @brief     从数组中检索指定索引的项
  257.    * @param     array cJSON 数组
  258.    * @param     index 索引
  259.    * @return    cJSON* 检索到的项,失败返回 NULL
  260.    */
  261.   CJSON_PUBLIC(cJSON *)  cJSON_GetArrayItem(const cJSON *array, int index);
  262.   /* Get item "string" from object. Case insensitive. */
  263.   /**
  264.    * @name      cJSON_GetObjectItem
  265.    * @brief     从对象中获取指定名称的项(不区分大小写)
  266.    * @param     object cJSON 对象
  267.    * @param     string 项的名称
  268.    * @return    cJSON* 检索到的项
  269.    */
  270.   CJSON_PUBLIC(cJSON *)  cJSON_GetObjectItem(const cJSON *const object, const char *const string);
  271.   /**
  272.    * @name      cJSON_GetObjectItemCaseSensitive
  273.    * @brief     从对象中获取指定名称的项(区分大小写)
  274.    * @param     object cJSON 对象
  275.    * @param     string 项的名称
  276.    * @return    cJSON* 检索到的项
  277.    */
  278.   CJSON_PUBLIC(cJSON *)  cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string);
  279.   /**
  280.    * @name      cJSON_HasObjectItem
  281.    * @brief     检查对象中是否存在指定名称的项
  282.    * @param     object cJSON 对象
  283.    * @param     string 项的名称
  284.    * @return    cJSON_bool 存在返回 1,不存在返回 0
  285.    */
  286.   CJSON_PUBLIC(cJSON_bool)  cJSON_HasObjectItem(const cJSON *object, const char *string);
  287.   /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
  288.   /**
  289.    * @name      cJSON_GetErrorPtr
  290.    * @brief     获取解析失败的错误指针
  291.    * @return    const char* 错误指针
  292.    */
  293.   CJSON_PUBLIC(const char *)  cJSON_GetErrorPtr(void);
  294.   /* Check item type and return its value */
  295.   /**
  296.    * @name      cJSON_GetStringValue
  297.    * @brief     检查项类型并返回其字符串值
  298.    * @param     item cJSON 项
  299.    * @return    char* 字符串值
  300.    */
  301.   CJSON_PUBLIC(char *)  cJSON_GetStringValue(const cJSON *const item);
  302.   /**
  303.    * @name      cJSON_GetNumberValue
  304.    * @brief     检查项类型并返回其数值
  305.    * @param     item cJSON 项
  306.    * @return    double 数值
  307.    */
  308.   CJSON_PUBLIC(double)  cJSON_GetNumberValue(const cJSON *const item);
  309.   /* These functions check the type of an item */
  310.   /* 以下函数检查项的类型 */
  311.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsInvalid(const cJSON *const item);
  312.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsFalse(const cJSON *const item);
  313.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsTrue(const cJSON *const item);
  314.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsBool(const cJSON *const item);
  315.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsNull(const cJSON *const item);
  316.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsNumber(const cJSON *const item);
  317.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsString(const cJSON *const item);
  318.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsArray(const cJSON *const item);
  319.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsObject(const cJSON *const item);
  320.   CJSON_PUBLIC(cJSON_bool)  cJSON_IsRaw(const cJSON *const item);
  321.   /* These calls create a cJSON item of the appropriate type. */
  322.   /* 以下函数创建适当类型的 cJSON 项 */
  323.   CJSON_PUBLIC(cJSON *)  cJSON_CreateNull(void);
  324.   CJSON_PUBLIC(cJSON *)  cJSON_CreateTrue(void);
  325.   CJSON_PUBLIC(cJSON *)  cJSON_CreateFalse(void);
  326.   CJSON_PUBLIC(cJSON *)  cJSON_CreateBool(cJSON_bool boolean);
  327.   CJSON_PUBLIC(cJSON *)  cJSON_CreateNumber(double num);
  328.   CJSON_PUBLIC(cJSON *)  cJSON_CreateString(const char *string);
  329.   /* raw json */
  330.   /* 原始 JSON */
  331.   CJSON_PUBLIC(cJSON *)  cJSON_CreateRaw(const char *raw);
  332.   CJSON_PUBLIC(cJSON *)  cJSON_CreateArray(void);
  333.   CJSON_PUBLIC(cJSON *)  cJSON_CreateObject(void);
  334.   /* Create a string where valuestring references a string so
  335.    * it will not be freed by cJSON_Delete */
  336.   /**
  337.    * @name      cJSON_CreateStringReference
  338.    * @brief     创建一个字符串引用项,valuestring 引用一个字符串,因此不会被 cJSON_Delete 释放
  339.    * @param     string 字符串
  340.    * @return    cJSON* 创建的字符串引用项
  341.    */
  342.   CJSON_PUBLIC(cJSON *)  cJSON_CreateStringReference(const char *string);
  343.   /* Create an object/array that only references it's elements so
  344.    * they will not be freed by cJSON_Delete */
  345.   /**
  346.    * @name      cJSON_CreateObjectReference
  347.    * @brief     创建一个对象引用项,引用其元素,因此不会被 cJSON_Delete 释放
  348.    * @param     child 子对象
  349.    * @return    cJSON* 创建的对象引用项
  350.    */
  351.   CJSON_PUBLIC(cJSON *)  cJSON_CreateObjectReference(const cJSON *child);
  352.   /**
  353.    * @name      cJSON_CreateArrayReference
  354.    * @brief     创建一个数组引用项,引用其元素,因此不会被 cJSON_Delete 释放
  355.    * @param     child 子数组
  356.    * @return    cJSON* 创建的数组引用项
  357.    */
  358.   CJSON_PUBLIC(cJSON *)  cJSON_CreateArrayReference(const cJSON *child);
  359.   /* These utilities create an Array of count items.
  360.    * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
  361.   /**
  362.    * @name      cJSON_CreateIntArray
  363.    * @brief     创建一个包含整数数组的 cJSON 项
  364.    * @param     numbers 整数数组
  365.    * @param     count 数组元素数量
  366.    * @return    cJSON* 创建的整数数组项
  367.    * @note      参数 count 不能大于整数数组的元素数量,否则数组访问将越界
  368.    */
  369.   CJSON_PUBLIC(cJSON *)  cJSON_CreateIntArray(const int *numbers, int count);
  370.   /**
  371.    * @name      cJSON_CreateFloatArray
  372.    * @brief     创建一个包含浮点数组的 cJSON 项
  373.    * @param     numbers 浮点数组
  374.    * @param     count 数组元素数量
  375.    * @return    cJSON* 创建的浮点数组项
  376.    * @note      参数 count 不能大于浮点数组的元素数量,否则数组访问将越界
  377.    */
  378.   CJSON_PUBLIC(cJSON *)  cJSON_CreateFloatArray(const float *numbers, int count);
  379.   /**
  380.    * @name      cJSON_CreateDoubleArray
  381.    * @brief     创建一个包含双精度数组的 cJSON 项
  382.    * @param     numbers 双精度数组
  383.    * @param     count 数组元素数量
  384.    * @return    cJSON* 创建的双精度数组项
  385.    * @note      参数 count 不能大于双精度数组的元素数量,否则数组访问将越界
  386.    */
  387.   CJSON_PUBLIC(cJSON *)  cJSON_CreateDoubleArray(const double *numbers, int count);
  388.   /**
  389.    * @name      cJSON_CreateStringArray
  390.    * @brief     创建一个包含字符串数组的 cJSON 项
  391.    * @param     strings 字符串数组
  392.    * @param     count 数组元素数量
  393.    * @return    cJSON* 创建的字符串数组项
  394.    * @note
  395.    *
  396.    */
  397.   CJSON_PUBLIC(cJSON *)  cJSON_CreateStringArray(const char *const *strings, int count);
  398.   /* Append item to the specified array/object. */
  399.   /**
  400.    * @name      cJSON_AddItemToArray
  401.    * @brief     将项添加到指定的数组中
  402.    * @param     array cJSON 数组
  403.    * @param     item 要添加的项
  404.    * @return    cJSON_bool 成功返回 1,失败返回 0
  405.    */
  406.   CJSON_PUBLIC(cJSON_bool)  cJSON_AddItemToArray(cJSON *array, cJSON *item);
  407.   /*@name cJSON_AddItemToObject
  408.    *@brief 将项添加到指定的对象中
  409.    *@param object cJSON 对象
  410.    *@param string 项的名称
  411.    *@param item 要添加的项
  412.    *@ return cJSON_bool 成功返回 1,失败返回 0 *
  413.    */
  414.   CJSON_PUBLIC(cJSON_bool)  cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
  415.   /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
  416.    * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
  417.    * writing to `item->string` */
  418.   /**
  419.    * @name      cJSON_AddItemToObjectCS
  420.    * @brief     将项添加到指定的对象中,当字符串是 const 时使用
  421.    * @param     object cJSON 对象
  422.    * @param     string 项的名称
  423.    * @param     item 要添加的项
  424.    * @return    cJSON_bool 成功返回 1,失败返回 0
  425.    * @note      当使用此函数时,确保在写入 `item->string` 之前始终检查 (item->type & cJSON_StringIsConst) 是否为零
  426.    */
  427.   CJSON_PUBLIC(cJSON_bool)  cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
  428.   /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
  429.   /**
  430.    * @name      cJSON_AddItemReferenceToArray
  431.    * @brief     将项的引用添加到指定的数组中
  432.    * @param     array cJSON 数组
  433.    * @param     item 要添加的项
  434.    * @return    cJSON_bool 成功返回 1,失败返回 0
  435.    * @note      使用此函数时,您希望将现有的 cJSON 添加到新的 cJSON 中,但不希望破坏现有的 cJSON
  436.    */
  437.   CJSON_PUBLIC(cJSON_bool)  cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
  438.   /**
  439.    * @name      cJSON_AddItemReferenceToObject
  440.    * @brief     将项的引用添加到指定的对象中
  441.    * @param     object cJSON 对象
  442.    * @param     string 项的名称
  443.    * @param     item 要添加的项
  444.    * @return    cJSON_bool 成功返回 1,失败返回 0
  445.    * @note      使用此函数时,您希望将现有的 cJSON 添加到新的 cJSON 中,但不希望破坏现有的 cJSON
  446.    */
  447.   CJSON_PUBLIC(cJSON_bool)  cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
  448.   /* Remove/Detach items from Arrays/Objects. */
  449.   /**
  450.    * @name      cJSON_DetachItemViaPointer
  451.    * @brief     从父对象中分离指定的项
  452.    * @param     parent 父对象
  453.    * @param     item 要分离的项
  454.    * @return    cJSON* 分离的项
  455.    */
  456.   CJSON_PUBLIC(cJSON *)  cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item);
  457.   /**
  458.    * @name      cJSON_DetachItemFromArray
  459.    * @brief     从数组中分离指定索引的项
  460.    * @param     array cJSON 数组
  461.    * @param     which 索引
  462.    * @return    cJSON* 分离的项
  463.    */
  464.   CJSON_PUBLIC(cJSON *)  cJSON_DetachItemFromArray(cJSON *array, int which);
  465.   /**
  466.    * @name      cJSON_DeleteItemFromArray
  467.    * @brief     从数组中删除指定索引的项
  468.    * @param     array cJSON 数组
  469.    * @param     which 索引
  470.    */
  471.   CJSON_PUBLIC(void)  cJSON_DeleteItemFromArray(cJSON *array, int which);
  472.   /**
  473.    * @name      cJSON_DetachItemFromObject
  474.    * @brief     从对象中分离指定名称的项(不区分大小写)
  475.    * @param     object cJSON 对象
  476.    * @param     string 项的名称
  477.    * @return    cJSON* 分离的项
  478.    */
  479.   CJSON_PUBLIC(cJSON *)  cJSON_DetachItemFromObject(cJSON *object, const char *string);
  480.   /**
  481.    * @name      cJSON_DetachItemFromObjectCaseSensitive
  482.    * @brief     从对象中分离指定名称的项(区分大小写)
  483.    * @param     object cJSON 对象
  484.    * @param     string 项的名称
  485.    * @return    cJSON* 分离的项
  486.    */
  487.   CJSON_PUBLIC(cJSON *)  cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
  488.   /**
  489.    * @name      cJSON_DeleteItemFromObject
  490.    * @brief     从对象中删除指定名称的项(不区分大小写)
  491.    * @param     object cJSON 对象
  492.    * @param     string 项的名称
  493.    */
  494.   CJSON_PUBLIC(void)  cJSON_DeleteItemFromObject(cJSON *object, const char *string);
  495.   /**
  496.    * @name      cJSON_DeleteItemFromObjectCaseSensitive
  497.    * @brief     从对象中删除指定名称的项(区分大小写)
  498.    * @param     object cJSON 对象
  499.    * @param     string 项的名称
  500.    */
  501.   CJSON_PUBLIC(void)  cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
  502.   /* Update array items. */
  503.   /**
  504.    * @name      cJSON_InsertItemInArray
  505.    * @brief     在数组中插入项,将现有项右移
  506.    * @param     array cJSON 数组
  507.    * @param     which 插入位置的索引
  508.    * @param     newitem 新项
  509.    * @return    cJSON_bool 成功返回 1,失败返回 0
  510.    */
  511.   CJSON_PUBLIC(cJSON_bool)  cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
  512.   /**
  513.    * @name      cJSON_ReplaceItemViaPointer
  514.    * @brief     用新项替换父对象中的指定项
  515.    * @param     parent 父对象
  516.    * @param     item 要替换的项
  517.    * @param     replacement 新项
  518.    * @return    cJSON_bool 成功返回 1,失败返回 0
  519.    */
  520.   CJSON_PUBLIC(cJSON_bool)  cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement);
  521.   /**
  522.    * @name      cJSON_ReplaceItemInArray
  523.    * @brief     用新项替换数组中指定索引的项
  524.    * @param     array cJSON 数组
  525.    * @param     which 索引
  526.    * @param     newitem 新项
  527.    * @return    cJSON_bool 成功返回 1,失败返回 0
  528.    */
  529.   CJSON_PUBLIC(cJSON_bool)  cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
  530.   /**
  531.    * @name      cJSON_ReplaceItemInObject
  532.    * @brief     用新项替换对象中指定名称的项(不区分大小写)
  533.    * @param     object cJSON 对象
  534.    * @param     string 项的名称
  535.    * @param     newitem 新项
  536.    * @return    cJSON_bool 成功返回 1,失败返回 0
  537.    */
  538.   CJSON_PUBLIC(cJSON_bool)  cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
  539.   /**
  540.    * @name      cJSON_ReplaceItemInObjectCaseSensitive
  541.    * @brief     用新项替换对象中指定名称的项(区分大小写)
  542.    * @param     object cJSON 对象
  543.    * @param     string 项的名称
  544.    * @param     newitem 新项
  545.    * @return    cJSON_bool 成功返回 1,失败返回 0
  546.    */
  547.   CJSON_PUBLIC(cJSON_bool)  cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem);
  548.   /* Duplicate a cJSON item */
  549.   /**
  550.    * @name      cJSON_Duplicate
  551.    * @brief     复制一个 cJSON 项
  552.    * @param     item 要复制的项
  553.    * @param     recurse 是否递归复制子项
  554.    * @return    cJSON* 复制后的项
  555.    * @note      复制将创建一个新的、与传递的项相同的 cJSON 项,在新内存中,需要释放。
  556.    *            当 recurse!=0 时,它将复制连接到该项的任何子项。返回的项的 item->next 和 ->prev 指针始终为零。
  557.    */
  558.   CJSON_PUBLIC(cJSON *)  cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
  559.   /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
  560.    * need to be released. With recurse!=0, it will duplicate any children connected to the item.
  561.    * The item->next and ->prev pointers are always zero on return from Duplicate. */
  562.   /* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
  563.    * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
  564.   /**
  565.    * @name      cJSON_Compare
  566.    * @brief     递归比较两个 cJSON 项是否相等。如果 a 或 b 为 NULL 或无效,它们将被视为不相等。
  567.    * @param     a 第一个 cJSON 项
  568.    * @param     b 第二个 cJSON 项
  569.    * @param     case_sensitive 是否区分大小写
  570.    * @return    cJSON_bool 相等返回 1,不相等返回 0
  571.    */
  572.   CJSON_PUBLIC(cJSON_bool)  cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive);
  573.   /* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
  574.    * The input pointer json cannot point to a read-only address area, such as a string constant,
  575.    * but should point to a readable and writable address area. */
  576.   /**
  577.    * @name      cJSON_Minify
  578.    * @brief     压缩字符串,去除字符串中的空白字符(如 ' ', '\t', '\r', '\n')
  579.    * @param     json 要压缩的字符串
  580.    * @note      输入指针 json 不能指向只读地址区域,如字符串常量,而应指向可读写的地址区域。
  581.    */
  582.   CJSON_PUBLIC(void)  cJSON_Minify(char *json);
  583.   /* Helper functions for creating and adding items to an object at the same time.
  584.    * They return the added item or NULL on failure. */
  585.   /**
  586.    * @name      cJSON_AddNullToObject
  587.    * @brief     创建并添加一个空项到对象中
  588.    * @param     object cJSON 对象
  589.    * @param     name 项的名称
  590.    * @return    cJSON* 添加的项,失败返回 NULL
  591.    */
  592.   CJSON_PUBLIC(cJSON *)  cJSON_AddNullToObject(cJSON *const object, const char *const name);
  593.   /**
  594.    * @name      cJSON_AddTrueToObject
  595.    * @brief     创建并添加一个 true 项到对象中
  596.    * @param     object cJSON 对象
  597.    * @param     name 项的名称
  598.    * @return    cJSON* 添加的项,失败返回 NULL
  599.    */
  600.   CJSON_PUBLIC(cJSON *)  cJSON_AddTrueToObject(cJSON *const object, const char *const name);
  601.   /**
  602.    * @name      cJSON_AddFalseToObject
  603.    * @brief     创建并添加一个 false 项到对象中
  604.    * @param     object cJSON 对象
  605.    * @param     name 项的名称
  606.    * @return    cJSON* 添加的项,失败返回 NULL
  607.    */
  608.   CJSON_PUBLIC(cJSON *)  cJSON_AddFalseToObject(cJSON *const object, const char *const name);
  609.   /**
  610.    * @name      cJSON_AddBoolToObject
  611.    * @brief     创建并添加一个布尔项到对象中
  612.    * @param     object cJSON 对象
  613.    * @param     name 项的名称
  614.    * @param     boolean 布尔值
  615.    * @return    cJSON* 添加的项,失败返回 NULL
  616.    */
  617.   CJSON_PUBLIC(cJSON *)  cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean);
  618.   /**
  619.    * @name      cJSON_AddNumberToObject
  620.    * @brief     创建并添加一个数字项到对象中
  621.    * @param     object cJSON 对象
  622.    * @param     name 项的名称
  623.    * @param     number 数值
  624.    * @return    cJSON* 添加的项,失败返回 NULL
  625.    */
  626.   CJSON_PUBLIC(cJSON *)  cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number);
  627.   /**
  628.    * @name      cJSON_AddStringToObject
  629.    * @brief     创建并添加一个字符串项到对象中
  630.    * @param     object cJSON 对象
  631.    * @param     name 项的名称
  632.    * @param     string 字符串值
  633.    * @return    cJSON* 添加的项,失败返回 NULL
  634.    */
  635.   CJSON_PUBLIC(cJSON *)  cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string);
  636.   /**
  637.    * @name      cJSON_AddRawToObject
  638.    * @brief     创建并添加一个原始 JSON 项到对象中
  639.    * @param     object cJSON 对象
  640.    * @param     name 项的名称
  641.    * @param     raw 原始 JSON 字符串
  642.    * @return    cJSON* 添加的项,失败返回 NULL
  643.    */
  644.   CJSON_PUBLIC(cJSON *)  cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw);
  645.   /**
  646.    * @name      cJSON_AddObjectToObject
  647.    * @brief     创建并添加一个对象项到对象中
  648.    * @param     object cJSON 对象
  649.    * @param     name 项的名称
  650.    * @return    cJSON* 添加的项,失败返回 NULL
  651.    */
  652.   CJSON_PUBLIC(cJSON *)  cJSON_AddObjectToObject(cJSON *const object, const char *const name);
  653.   /**
  654.    * @name      cJSON_AddArrayToObject
  655.    * @brief     创建并添加一个数组项到对象中
  656.    * @param     object cJSON 对象
  657.    * @param     name 项的名称
  658.    * @return    cJSON* 添加的项,失败返回 NULL
  659.    */
  660.   CJSON_PUBLIC(cJSON *)  cJSON_AddArrayToObject(cJSON *const object, const char *const name);
  661. /* When assigning an integer value, it needs to be propagated to valuedouble too. */
  662. #define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
  663.   /* helper for the cJSON_SetNumberValue macro */
  664.   /**
  665.    * @name      cJSON_SetNumberHelper
  666.    * @brief     帮助宏 cJSON_SetNumberValue 设置数值
  667.    * @param     object cJSON 对象
  668.    * @param     number 数值
  669.    * @return    double 设置后的数值
  670.    */
  671.   CJSON_PUBLIC(double)  cJSON_SetNumberHelper(cJSON *object, double number);
  672. #define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
  673.   /* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
  674.   /**
  675.    * @name      cJSON_SetValuestring
  676.    * @brief     更改 cJSON_String 对象的 valuestring 值,仅当对象类型为 cJSON_String 时生效
  677.    * @param     object cJSON 对象
  678.    * @param     valuestring 新的字符串值
  679.    * @return    char* 更改后的字符串
  680.    */
  681.   CJSON_PUBLIC(char *)  cJSON_SetValuestring(cJSON *object, const char *valuestring);
  682. /* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
  683. #define cJSON_SetBoolValue(object, boolValue) ( \
  684.     (object != NULL && ((object)->type & (cJSON_False | cJSON_True))) ? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) | ((boolValue) ? cJSON_True : cJSON_False) : cJSON_Invalid)
  685. /* Macro for iterating over an array or object */
  686. /* */
  687. /*  */
  688. /**
  689. * 用于在数组或对象上迭代的宏 , 用于遍历一个cJSON数组中的每一个元素
  690. *
  691. * element 是当前遍历到的cJSON元素.
  692. * array 是需要遍历的cJSON数组。
  693. * for 循环的初始化部分:element = (array != NULL) ? (array)->child : NULL,如果 array 非空,则将 element 初始化为 array 的第一个子元素,否则初始化为 NULL。
  694. * 循环的条件部分:element != NULL,只要 element 不为空,循环就会继续。
  695. * 循环的迭代部分:element = element->next,将 element 更新为下一个兄弟元素。
  696. */
  697. #define cJSON_ArrayForEach(element, array) for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
  698.   /* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
  699.   /**
  700.    * @name      cJSON_malloc
  701.    * @brief     使用已经设置的 malloc 函数分配内存
  702.    * @param     size 内存大小
  703.    * @return    void* 分配的内存指针
  704.    */
  705.   CJSON_PUBLIC(void *)  cJSON_malloc(size_t size);
  706.   /**
  707.    * @name      cJSON_free
  708.    * @brief     使用已经设置的 free 函数释放内存
  709.    * @param     object 要释放的内存指针
  710.    */
  711.   CJSON_PUBLIC(void)  cJSON_free(void *object);
  712. #ifdef __cplusplus
  713. }
  714. #endif
  715. #endif
  716. // clang-format on
复制代码
cJSON.c

DaveGamble/cJSON: Ultralightweight JSON parser in ANSI C (github.com)  cJSON库 基于C语言的一个开源项目
去这里下载cJSON.c文件及原版cJSON.h文件.
参考链接

测试链接:
  1. 未来天气
  2. https://api.seniverse.com/v3/weather/daily.json?key=你的私钥&location=guangzhou&language=en&unit=c&start=0&days=3
  3. 实况天气
  4. https://api.seniverse.com/v3/weather/now.json?key=你的私钥&location=guangzhou&language=en&unit=c
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

温锦文欧普厨电及净水器总代理

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表