首页 > 其他分享 >Exercise:JSON解析

Exercise:JSON解析

时间:2024-06-11 23:54:46浏览次数:8  
标签:socket cJSON json JSON 解析 response Exercise addr

练习:利用某些平台(聚合 API、百度 A、科大讯飞 API)的 API接口,利用 HTTP 协议向服务器发送请求,并接受服务器的响应,要求利用cISON库对服务器的响应数据进行解析,并输出到终端。

/***************************************************************************************************** 
 * Function:        parse_json_response
 * Description:     解析从HTTP响应中接收到的JSON字符串,并打印出格式化的JSON以及提取的关键信息。
 * Calls:           cJSON_Parse, cJSON_Print, cJSON_GetObjectItem, cJSON_GetArrayItem, cJSON_Delete
 * Called By:       main
 * Input:           const char *response - 指向包含HTTP头和JSON响应体的完整响应字符串的指针。
 * Output:          打印到标准输出的格式化JSON字符串和提取的关键信息。
 * Return:          void - 此函数不返回任何值。
 * Others:          
 *                  1.待解析的JSON
 *                  {
 *                      "results": [{
 *                                    "id":   "WX4FBXXFKE4F",
 *                                    "name": "北京",
 *                                    "country":      "CN",
 *                                    "path": "北京,北京,中国",
 *                                    "timezone":     "Asia/Shanghai",
 *                                    "timezone_offset":      "+08:00"
 *                                }]
 *                   }
 *                  2.此函数假设response参数是一个有效的HTTP响应,包含一个JSON响应体。
 *                    如果response格式不正确或解析失败,将打印错误信息到标准错误。
 *                  3.注意HTTP请求后会有HTTP响应头和JSON响应体,在JSON解析时要分离出来
 *                  4.请求信息过于大时,会申请的堆空间可能会无法满足,要考虑空间大小
 *                  5.当HTTP回复的消息不完整时,会出现段错误,要让recv()函数循环接收完全。
 *                  6.将宏定义中的KEY,替换成自己的
 *                  7.本文采用“心知天气”的相关API
 *
 * CopyRight (c)  2023-2024   [email protected]   All Right Reserved
 *********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "cJSON.h"

#define PORT 80
#define HOSTNAME "api.seniverse.com"
#define KEY "your_key"
#define LOCAL "guangzhou"
#define BUFFSIZE 102400


/**************************************************  创建TCP套接字 **********************************************************/
int create_tcp_socket() {
    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (tcp_socket == -1) {
        fprintf(stderr, "tcp socket error, errno:%d, %s\n", errno, strerror(errno));
        exit(1);
    }
    return tcp_socket;
}


/**************************************************  解析主机名 **********************************************************/
struct sockaddr_in resolve_hostname(const char *hostname) {
    struct hostent *he = gethostbyname(hostname);
    if (he == NULL) {
        fprintf(stderr, "gethostbyname error\n");
        exit(1);
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr = *((struct in_addr *)he->h_addr);
    return addr;
}


/**************************************************  连接到服务器 **********************************************************/
void connect_to_server(int socket, struct sockaddr_in addr) {
    if (connect(socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        fprintf(stderr, "connect error, errno:%d, %s\n", errno, strerror(errno));
        exit(1);
    }
}


/**************************************************  发送HTTP请求 **********************************************************/
void send_http_request(int socket, const char *hostname, const char *key) {
    char reqbuf[1024];

    sprintf(reqbuf,    
        "GET https://api.seniverse.com/v3/location/search.json?key=%s&q=WX4FBXXFKE4F HTTP/1.1\r\n"
        "Host:%s\r\n"
        "\r\n",
        key, hostname);

    

    if (send(socket, reqbuf, strlen(reqbuf), 0) < 0) {
        fprintf(stderr, "send error, errno:%d, %s\n", errno, strerror(errno));
        exit(1);
    }
}

/**************************************************  接收HTTP响应 **********************************************************/
char *receive_http_response(int socket) {
    char *response = malloc(BUFFSIZE); // 分配内存以接收响应
    if (response == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(1);
    }

    int bytes_received;
    int total_bytes_received = 0;
    do {
        bytes_received = recv(socket, response + total_bytes_received, BUFFSIZE - total_bytes_received - 1, 0);
        if (bytes_received > 0) {
            total_bytes_received += bytes_received;
        }
    } while (bytes_received > 0);

    if (bytes_received < 0) {
        fprintf(stderr, "recv error, errno:%d, %s\n", errno, strerror(errno));
        free(response);
        exit(1);
    }

    response[total_bytes_received] = '\0'; // 确保响应字符串以空字符结尾
    return response;
}

/**************************************************  解析JSON响应 **********************************************************/
void parse_json_response(const char *response) {
    // 查找HTTP响应头和响应体之间的空行,将HTTP响应头和JSON响应体分开
    const char *json_data = strstr(response, "\r\n\r\n");
    if (json_data != NULL) {
        json_data += 4; // 跳过空行,指向JSON数据的开始
    } else {
        fprintf(stderr, "Failed to find the end of the HTTP headers.\n");
        return;
    }

    cJSON *json = cJSON_Parse(json_data);
    if (json == NULL) {
        fprintf(stderr, "Error before: [%s]\n", cJSON_GetErrorPtr());
    } else {
        char *json_str = cJSON_Print(json);
        printf("%s\n", json_str); // 打印格式化的JSON字符串
        cJSON * result = cJSON_GetObjectItem(json,"results");
        cJSON * array  = cJSON_GetArrayItem(result,0);
        cJSON * id = cJSON_GetObjectItem(array,"id");
        cJSON * name = cJSON_GetObjectItem(array,"name");
        cJSON * country = cJSON_GetObjectItem(array,"country");
        cJSON * path = cJSON_GetObjectItem(array,"path");
        cJSON * timezone = cJSON_GetObjectItem(array,"timezone");
        cJSON * timezone_offset = cJSON_GetObjectItem(array,"timezone_offset");


        printf("id       : %s\n", id->valuestring);
        printf("name     : %s\n", name->valuestring);
        printf("country  : %s\n", country->valuestring);
        printf("path     : %s\n", path->valuestring);
        printf("timezone : %s\n", timezone->valuestring);
        printf("timezone_offset : %s\n", timezone_offset->valuestring);

        free(json_str);
        cJSON_Delete(json);
    }
}

int main(int argc, char const *argv[]) {
    int tcp_socket = create_tcp_socket();
    struct sockaddr_in server_addr = resolve_hostname(HOSTNAME);
    connect_to_server(tcp_socket, server_addr);
    send_http_request(tcp_socket, HOSTNAME, KEY);
    char *response = receive_http_response(tcp_socket);
    parse_json_response(response);
    free(response);                 // 释放接收到的响应
    close(tcp_socket);              // 关闭套接字
    return 0;
}

标签:socket,cJSON,json,JSON,解析,response,Exercise,addr
From: https://www.cnblogs.com/banon/p/18243042

相关文章

  • 基于服务器响应的实时天气数据进行JSON解析的详细代码及其框架
    #include<netinet/in.h>#include<arpa/inet.h>#include<stdio.h>#include<errno.h>#include<sys/socket.h>#include<netinet/in.h>#include<netinet/ip.h>#include<arpa/inet.h>#include<sys/socket.h&g......
  • http与cJSON练习
    http与cJSON练习/*****************************************************************************************************weather_test.c*练习tcp连接,与http协议,调用服务器接口,实现获取特定城市的天气信息,并用cJSO......
  • 利用聚合API平台的API接口,利用HTTP协议向服务器发送请求,并接受服务器的响应,要求利用cJ
    目录题目分析代码结果题目利用聚合API平台的API接口,利用HTTP协议向服务器发送请求,并接受服务器的响应,要求利用cJSON库对服务器的响应数据进行解析,并输出到终端分析1.需从源代码网站GitHub或SourceForge代码网站下载cJSON库及阅读下载的README相关手册如何使用cJSON库;2.使用......
  • 网络编程练习题---利用cJSON库对服务器返回的JSON格式数据完成解析
    目录题目注意事项实现代码结果展示相关接口指引题目利用某些平台(聚合API、百度AI、科大讯飞API)的API接口,利用HTTP协议向服务器发送请求,并接受服务器的响应,要求利用cJSON库对服务器的响应数据进行解析,并输出到终端。注意事项1.预测的日期开始时间为2010-01-012."老黄历"API......
  • cJSON学习及简单应用小结
    JSON简介JSON(JavaScriptObjectNotation,JavaScript对象表示法)是一种轻量级的数据交换格式。它基于ECMAScript(欧洲计算机制造商协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON成为理想的数据交换语言。以下是JSON......
  • 探索Java的奥秘:网络编程、反射与注解的深度解析
    Java,作为一门功能强大的编程语言,在网络编程、反射和注解方面提供了丰富的支持和灵活的应用。本文将深入探讨这些概念,并通过实际例子来加深理解。一、Java网络编程1.1网络编程基础网络编程是Java语言的一大亮点,它允许我们创建能够通过网络进行通信的程序。Java提供了java......
  • fastjson1
    @目录前言分析复制文件清空文件出现问题和分析问题解决分析问题再次出现问题再次分析最终结果读取文件分析poc拓宽场景极限环境poc优化修改再次优化poc的分析写入文件SafeFileOutputStream写文件java8无依赖读文件在commons-io库下的写入文件原因利用链分析组合poc出现问题和分析......
  • 深入解析MySQL Threads_running:监控、诊断与性能优化策略
    基本概念​在MySQL中,Threads_running是一个用于监控数据库并发连接数的指标。它表示当前正在执行的线程数。当该值超过数据库能够处理的最大连接数时,可能会导致数据库性能下降甚至崩溃。线程数过多会由于上下文切换、锁等待等问题从而导致性能急剧下降。设置Threads_......
  • 服务发现全流程解析-APOLLO7.0
    cyber服务发现完全依赖于fastDDS,下面从底层一步一步看下服务发现的整个过程。topology_manager.cc首先从这个类看起,这个类是和dds接壤的,dds发现后,完全由这个类接管,然后整体开始通信。TopologyManager::TopologyManager():init_(false),node_manager_(nullptr),......
  • 优化MySQL连接管理:深入解析max_connections参数与解决Too Many Connections策略
    前言​在现代的数据库管理中,合理配置max_connections参数对于确保MySQL数据库的稳定性和高效性至关重要。本文将深入探讨max_connections的基本概念,分析导致“Toomanyconnections”错误的常见原因,并提供一系列解决方案,以帮助数据库管理员和开发者优化数据库性能。基本......