ClickHouse 25.3 json列类型使用示例

JSON已经成为现代数据系统中处理半结构化和非结构化数据的通用语言。无论是在日志记录和可观察性场景、实时数据流、移动应用存储还是机器学习管道中,JSON的灵活结构使其成为跨分布式系统捕获和传输数据的首选格式。

测试环境

docker镜像
Official Images clickhouse
docker pull clickhouse:25.4.5.24

docker run -d --rm --name ch25 --ulimit nofile=262144:262144 clickhouse:25.4.5.24


docker run -d -p 18123:8123 -p19000:9000 -e CLICKHOUSE_PASSWORD=thinker --name ch25 --ulimit nofile=262144:262144 clickhouse:25.4.5.24

json列类型

ClickHouse 从24.8版本提供了专为半结构化和动态数据设计的原生JSON列类型,需要注意的是它是列类型,不是数据格式, 只有当数据结构是动态的,而不是仅仅存储JSON时,用户才应该使用JSON类型

在ClickHouse中,开源JSON数据类型在25.3版本中被标记为生产就绪。在以前的版本中,不建议在生产中使用这种类型。

在使用25.3以后的版本就可以使用JSON列类型了

何时使用json列类型

  • 有不可预测的键,可以随着时间的推移而改变。
  • 包含不同类型的值(例如,某个路径的值可能是字符串,也可能是数字)
  • 在严格类型不可行的情况下需要模式灵活性

如果您的数据结构是已知且一致的,则很少需要JSON类型,即使您的数据是JSON格式,数据特点如下:

  • 具有已知键的扁平结构:使用标准列类型,例如字符串。
  • 可预测嵌套:对这些结构使用元组、数组或嵌套类型。
  • 具有不同类型的可预测结构:考虑动态或变体类型。
    针对这种情况不要使用JSON列类型,但可以混合使用各种方法,如对可预测的顶级字段使用静态列,对有效负载的动态部分使用单个JSON列。

如何定义json列类型

要声明JSON类型的列,可以使用以下语法:

<column_name> JSON
(
    max_dynamic_paths=N, 
    max_dynamic_types=M, 
    some.path TypeName, 
    SKIP path.to.skip, 
    SKIP REGEXP 'paths_regexp'
)
  • max_dynamic_paths 默认为1024,json paths最大的数量,如果超过这个限制,所有其他路径将一起存储在一个结构中。
  • max_dynamic_types 默认为32
  • some.path TypeName根据需要指定子列的类型
  • SKIP path.to.skip 跳过不需要的path
  • SKIP REGEXP ‘path_regexp’ 设置路径表达式跳过不需要的path

函数

  • FORMAT PrettyJSONEachRow 指定select数据的输出格式
  • FORMAT JSONEachRow 指定insert的数据格式
  • FORMAT JSONAsObject 当表中只有一个JSON字段时,指定insert的数据格式
  • JSONAllPathsWithTypes(doc) 输出json字段的所有path及其类型
  • Using CAST with ::JSON
    • cast string to json: '{"a" : {"b" : 42},"c" : [1, 2, 3], "d" : "Hello, World!"}'::JSON AS json;
    • cast tuple to json:
    • Object(‘json’)toJSON`
-- 建表示例
CREATE TABLE test (json JSON(a.b UInt32, SKIP a.e)) ENGINE = Memory;
INSERT INTO test VALUES ('{"a" : {"b" : 42}, "c" : [1, 2, 3]}'), ('{"f" : "Hello, World!"}'), ('{"a" : {"b" : 43, "e" : 10}, "c" : [4, 5, 6]}');
SELECT json FROM test;


-- CAST from `String` to `JSON`
SELECT '{"a" : {"b" : 42},"c" : [1, 2, 3], "d" : "Hello, World!"}'::JSON AS json;

-- CAST from `Tuple` to `JSON`
SET enable_named_columns_in_function_tuple = 1;  
SELECT (tuple(42 AS b) AS a, [1, 2, 3] AS c, 'Hello, World!' AS d)::JSON AS json;

-- CAST from `Map` to `JSON`
--类型都使用string
SET enable_variant_type=1,
<think>好的,我现在需要帮助用户了解如何在Arduino中使用JSON版本7来解析通过HTTP下发的JSON数据。首先,我得回想一下Arduino常用的JSON库。用户提到的JSONv7可能是指ArduinoJson库的7.x版本,这个版本和之前的6.x在API上有一些变化,所以需要注意。 接下来,用户的需求是解析从HTTP获取的JSON数据。步骤大概包括:安装库、发送HTTP请求、解析响应。需要确认用户是否已经了解这些步骤,或者是否需要详细说明每个部分。 首先,安装库的部分。用户可能需要指导如何在Arduino IDE中安装ArduinoJson 7.x。通常通过库管理器搜索安装即可,但需要提醒用户确认版本是否正确。 然后,发送HTTP请求。这里可能需要使用到WiFi或以太网库,根据用户的硬件情况而定。例如,使用ESP8266或ESP32的话,可能需要使用WiFiClient或HTTPClient库。需要给出示例代码的大致结构,包括连接WiFi、发起GET请求、获取响应内容等步骤。 接下来是解析部分。使用ArduinoJson 7.x的话,DynamicJsonDocument被JsonDocument取代?或者可能还是类似的用法?需要查证一下。例如,创建JsonDocument对象,然后反序列化HTTP响应内容。然后如何提取字段,可能需要使用到[]运算符或者getMember等方法。要注意内存分配的问题,避免栈溢出,特别是在处理大JSON时,可能需要调整缓冲区大小。 另外,错误处理也很重要。例如,检查反序列化是否成功,处理网络请求失败的情况,以及JSON结构不符合预期的情况。需要提醒用户添加这些检查,以提高代码的健壮性。 可能还需要给出一个完整的示例代码框架,包括必要的头文件引用、WiFi连接部分、HTTP请求部分和JSON解析部分。同时,要指出常见的坑,比如内存不足、JSON结构变化导致的解析失败等。 最后,用户可能需要知道如何处理不同的JSON数据类型,比如字符串、数字、数组或嵌套对象。需要简要说明如何访问这些数据。 总结下来,回答的结构应该是:安装库、网络请求、解析步骤、示例代码、注意事项。需要确保使用ArduinoJson 7.x的语法,并和之前的版本区分开来,避免用户混淆。</think>在 Arduino 中使用 **ArduinoJson 7.x** 解析 HTTP 下发的 JSON 数据,步骤如下: --- ### 1. 安装库 - **ArduinoJson 库**:通过 Arduino IDE 的库管理器安装 **ArduinoJson 7.x**(确认版本 ≥ 7.0)。 - 菜单栏 → **工具 → 管理库** → 搜索 "ArduinoJson" → 安装。 --- ### 2. 网络请求获取 JSON 假设使用 **ESP8266/ESP32** 开发板,通过 HTTP GET 请求获取 JSON 数据: ```cpp #include <WiFiClient.h> #include <HTTPClient.h> const char* ssid = "你的WiFi名称"; const char* password = "你的WiFi密码"; const char* url = "http://example.com/api/data"; // JSON 数据地址 void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) delay(500); Serial.println("WiFi 已连接"); } String fetchJSON() { HTTPClient http; http.begin(url); int httpCode = http.GET(); String payload = ""; if (httpCode == HTTP_CODE_OK) { payload = http.getString(); } else { Serial.printf("HTTP 请求失败,错误码: %d\n", httpCode); } http.end(); return payload; } ``` --- ### 3. 解析 JSON 数据(ArduinoJson 7.x) ```cpp #include <ArduinoJson.h> void parseJSON(const String& json) { // 计算 JSON 所需内存(建议使用官方工具:https://arduinojson.org/v7/assistant/) const size_t capacity = JSON_OBJECT_SIZE(3) + 128; // 根据实际 JSON 调整 DynamicJsonDocument doc(capacity); // 反序列化 JSON DeserializationError error = deserializeJson(doc, json); if (error) { Serial.print("JSON 解析失败: "); Serial.println(error.c_str()); return; } // 提取字段(示例) const char* name = doc["name"]; // 字符串 int age = doc["age"]; // 整数 float temperature = doc["temp"]; // 浮点数 bool status = doc["isEnabled"]; // 布尔值 // 输出结果 Serial.println("解析结果:"); Serial.println(name); Serial.println(age); Serial.println(temperature, 2); // 保留两位小数 Serial.println(status ? "ON" : "OFF"); } void loop() { String json = fetchJSON(); if (json != "") { parseJSON(json); } delay(5000); // 每5秒请求一次 } ``` --- ### 4. 关键注意事项 1. **内存分配**:使用 `DynamicJsonDocument` 时需预估 JSON 大小,避免内存溢出。可通过 [ArduinoJson Assistant](https://arduinojson.org/v7/assistant/) 计算。 2. **错误处理**:检查 `deserializeJson()` 返回值,确保解析成功。 3. **数据类型**:使用正确的函数提取数据(如 `doc["key"].as<T>()` 强制类型转换)。 4. **嵌套对象**:逐层访问嵌套字段,例如 `doc["sensor"]["temperature"]`。 --- ### 示例 JSON 与解析对应关系 假设 HTTP 返回的 JSON 如下: ```json { "name": "Sensor01", "age": 5, "temp": 25.3, "isEnabled": true } ``` 代码中的 `doc["name"]` 将获取 `"Sensor01"`,其他字段同理。 --- 通过以上步骤,即可在 Arduino 中实现 HTTP 请求并解析 JSON 数据。根据实际 JSON 结构调整字段名称和解析逻辑即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

enjoy编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值