You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态生成JSON写入Avro文件后Snowflake出现转义字符问题

问题与解决方案

问题背景

向Avro文件写入数据(将同步至Snowflake),其中一个字段为动态结构的JSON——JSON结构仅在运行时确定,无法提前创建对应实体类序列化生成。目前用StringBuilder手动拼接JSON,同步到Snowflake后出现转义反斜杠,尝试Replace(@"\", string.Empty)无效。

相关代码与现象:

  • Field类定义:
public class Field { 
  public string Name { get; set; } 
  public string Value { get; set; } 
}
  • 手动拼接JSON的代码:
StringBuilder newJson = new StringBuilder();
newJson.Append("{");
foreach (Field requestedField in fields)
{
   newJson.Append($"\"{requestedField.Name}\": {FormatValue(requestedField.Value)}");
   if (requestedField != fields.Last())
     newJson.Append(", ");
}
newJson.Append("}");
  • 期望生成的JSON:
{
"ProductName": "Bucket",
"Price": 199,
"OrderCode": "G1234",
"Deleted": true
}
  • 实际Snowflake中出现转义的JSON:
{
\"ProductName\": \"Bucket\",
\"Price\": 199,
\"OrderCode\": \"G1234\",
\"Deleted\": true
}

核心原因

Avro序列化时会将string类型字段的特殊字符(如双引号)自动转义。你手动拼接的JSON被当作普通字符串处理,Avro会给双引号添加转义反斜杠,最终导致Snowflake中呈现带转义的内容。

解决方案

方案1:用动态Avro Record存储JSON结构(推荐)

直接基于运行时字段构建Avro的GenericRecord,让Avro以结构化方式存储数据,Snowflake读取时会自动解析为JSON对象,彻底避免转义问题。

代码示例:

using Avro;
using Avro.Generic;
using System.Collections.Generic;

// 1. 动态生成Avro Record Schema
List<Field> avroFields = new List<Field>();
foreach (var field in fields)
{
    Schema fieldSchema = field.Type.ToLower() switch
    {
        "bit" => BooleanSchema.Instance,
        "int" => Int32Schema.Instance,
        "bigint" => Int64Schema.Instance,
        "decimal" => DoubleSchema.Instance,
        "varchar" => StringSchema.Instance,
        _ => StringSchema.Instance
    };
    avroFields.Add(new Field(field.Name, fieldSchema));
}
RecordSchema dynamicSchema = RecordSchema.Create("DynamicRecord", avroFields);

// 2. 构建GenericRecord
GenericRecord dynamicRecord = new GenericRecord(dynamicSchema);
foreach (var field in fields)
{
    dynamicRecord[field.Name] = field.Type.ToLower() switch
    {
        "bit" => bool.Parse(field.Value),
        "int" => int.Parse(field.Value),
        "bigint" => long.Parse(field.Value),
        "decimal" => double.Parse(field.Value),
        _ => field.Value
    };
}

// 3. 将dynamicRecord作为目标字段的值写入Avro文件
// 替换原有Avro写入逻辑,将此record赋值给对应字段即可

方案2:用JSON库生成字符串,以字节数组写入Avro

若必须用字符串类型存储JSON,可将JSON转为字节数组写入Avro的bytes类型字段,避免Avro转义,再在Snowflake侧解析。

代码示例:

using Newtonsoft.Json.Linq;
using System.Text;

// 1. 用JObject构建正确的JSON结构
JObject jsonObj = new JObject();
foreach (var field in fields)
{
    jsonObj[field.Name] = field.Type.ToLower() switch
    {
        "bit" => bool.Parse(field.Value),
        "int" => int.Parse(field.Value),
        "decimal" => decimal.Parse(field.Value),
        _ => field.Value
    };
}
string jsonStr = jsonObj.ToString(Newtonsoft.Json.Formatting.None);

// 2. 转为字节数组写入Avro的bytes字段
byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonStr);

// 3. 将jsonBytes作为目标字段的值写入Avro文件

Snowflake读取时解析:

SELECT PARSE_JSON(TO_VARCHAR(json_bytes_field)) AS json_field FROM your_table;

内容的提问来源于stack exchange,提问作者Calid Xavier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:09:21