目录
1、介绍
2. 要求
3. 使用方法
3.1 样本数据
3.2 快速转换
3.3 使用POCO对象
3.4 使用投影
3.5 使用选择
- 下载 Cinchoo ETL 源码
- 下载 Cinchoo ETL 二进制文件 (.NET Core)
- 下载 Cinchoo ETL 二进制文件 (.NET Framework)
- 工作示例 1(.NET Fiddle)
- 工作示例 2 (.NET Fiddle)
- 工作示例 3 (.NET Fiddle)
- 工作示例 4(.NET Fiddle)
ChoETL是一个用于.NET的开源ETL(提取、转换和加载)框架。它是一个基于代码的库,用于在.NET环境中从多个来源提取数据、转换并加载到您自己的数据仓库中。您可以立即在数据仓库中拥有数据。
这个技巧讨论了使用Cinchoo ETL框架从JSON格式生成CSV文件。使用非常简单,只需几行代码,即可完成转换。您可以转换大文件,因为转换过程是基于流的、速度非常快且内存占用低。
2. 要求该框架库是使用.NET 4.5/.NET Core Frameworks用C#编写的。
3. 使用方法 3.1 样本数据让我们首先看一个转换以下JSON输入文件的简单示例。
清单 3.1.1 示例JSON数据输入文件(Orders.json)
{
"system": {
"created": "2021-08-01T13:33:37.123Z",
"by": "web"
},
"location": {
"id": 100,
"country": "DE"
},
"order": [
{
"OrderID": 22,
"OrderName": "Soda",
"OrderArticles": [
{
"Size": 33,
"ProductName": "Coke",
"ProductId": "999"
},
{
"Size": 66,
"ProductName": "Fanta",
"ProductId": "888"
},
{
"Size": 50,
"ProductName": "Pepsi",
"ProductId": "444"
}
],
"ProcessedId": 1001,
"Date": "2021-08-02"
},
{
"OrderID": 23,
"OrderName": "Beverage",
"OrderArticles": [
{
"Size": 44,
"ProductName": "Coke",
"ProductId": "999"
}
],
"ProcessedId": 1002,
"Date": "2021-08-03"
}
]
}
由于JSON消息是分层结构格式,因此您必须扁平化才能生成CSV文件。
假设您想生成以下CSV格式的输出。
清单 3.1.2 CSV数据输出文件(Orders.csv)
created;by;id;country;OrderID;OrderName;Size;ProductName;ProductId
2021-08-01T13:33:37.123Z;web;100;DE;22;Soda;33;Coke;999
2021-08-01T13:33:37.123Z;web;100;DE;22;Soda;66;Fanta;888
2021-08-01T13:33:37.123Z;web;100;DE;22;Soda;50;Pepsi;444
2021-08-01T13:33:37.123Z;web;100;DE;23;Beverage;44;Coke;999
首先要做的是安装ChoETL.JSON/ChoETL.JSON.NETStandard nuget包。为此,请在包管理器控制台中运行以下命令。
.NET Framework
Install-Package ChoETL.JSON
.NET Core
Install-Package ChoETL.JSON.NETStandard
现在ChoETL向程序添加命名空间。
using ChoETL;
这种方法展示了如何用一小段代码将JSON文件转换为CSV格式。不需要设置/POCO类。
清单 3.2.1 快速JSON到CSV文件转换
private static void QuickConversion()
{
StringBuilder csv = new StringBuilder();
using (var r = new ChoJSONReader("orders.json")
.Configure(c => c.FlattenNode = true)
.JsonSerializationSettings(s => s.DateParseHandling = DateParseHandling.None)
)
{
using (var w = new ChoCSVWriter(csv)
.WithDelimiter(";")
.WithFirstLineHeader()
.Configure(c => c.IgnoreDictionaryFieldPrefix = true)
)
{
w.Write(r);
}
}
Console.WriteLine(csv.ToString());
}
创建一个用于生成CSV ( orders.csv )文件的ChoCSVWriter实例。然后创建一个ChoJSONReader对象实例用于读取orders.json文件。这里通过使用JsonSerializationSettings(s => s.DateParseHandling = DateParseHandling.None)关闭datetime解析并将其作为文本处理。然后在CSV输出端,使用IgnoreDictionaryFieldPrefix为true告诉CSV解析不要在输出中添加父节点前缀。
示例Fiddle:C# Online Compiler | .NET Fiddle
3.3 使用POCO对象这种方法向您展示了如何定义POCO实体类并将它们用于转换过程。这种方法类型更安全,并且对转换过程进行了精细控制。使用json值填充对象后,使用LINQ为所需的CSV格式组合数据。
清单 3.3.1 映射类
public class System
{
[JsonProperty("created")]
public string Created { get; set; }
[JsonProperty("by")]
public string By { get; set; }
}
public class Location
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
}
public class OrderArticle
{
[JsonProperty("Size")]
public int Size { get; set; }
[JsonProperty("ProductName")]
public string ProductName { get; set; }
[JsonProperty("ProductId")]
public string ProductId { get; set; }
}
public class Order
{
[JsonProperty("OrderID")]
public int OrderID { get; set; }
[JsonProperty("OrderName")]
public string OrderName { get; set; }
[JsonProperty("OrderArticles")]
public List OrderArticles { get; set; }
[JsonProperty("ProcessedId")]
public int ProcessedId { get; set; }
[JsonProperty("Date")]
public string Date { get; set; }
}
public class OrderRoot
{
[JsonProperty("system")]
public System System { get; set; }
[JsonProperty("location")]
public Location Location { get; set; }
[JsonProperty("order")]
public List Orders { get; set; }
}
然后使用这个类如下进行文件的转换。
清单 3.3.2 使用POCO对象将JSON转换为CSV文件
private static void UsingPOCO()
{
StringBuilder csv = new StringBuilder();
using (var r = new ChoJSONReader("orders.json")
.UseJsonSerialization()
)
{
using (var w = new ChoCSVWriter(csv)
.WithDelimiter(";")
.WithFirstLineHeader())
{
w.Write(r.SelectMany(root =>
root.Orders
.SelectMany(order => order.OrderArticles
.Select(orderarticle => new
{
created = root.System.Created,
by = root.System.By,
id = root.Location.Id,
order.OrderID,
order.OrderName,
orderarticle.Size,
orderarticle.ProductName,
orderarticle.ProductId,
})
)
)
);
}
}
Console.WriteLine(csv.ToString());
}
Fiddle示例: C# Online Compiler | .NET Fiddle
3.4 使用投影此方法展示了如何使用LINQ投影方法将JSON文件转换为CSV文件。您可能知道,JSON是一种分层的、关系的和结构化的数据,而CSV不是。如果您有从JSON读取器以分层格式生成的对象,则必须使用LINQ投影展平并将它们提供给CSV写入器以创建CSV文件。下面的示例显示了如何做到这一点。
清单 3.4.1 使用投影将JSON转换为CSV文件
private static void UsingProjection()
{
StringBuilder csv = new StringBuilder();
using (var r = new ChoJSONReader("orders.json")
.JsonSerializationSettings(s => s.DateParseHandling = DateParseHandling.None)
)
{
using (var w = new ChoCSVWriter(csv)
.WithDelimiter(";")
.WithFirstLineHeader())
{
w.Write(r.SelectMany(root =>
((Array)root.order).Cast()
.SelectMany(order => ((Array)order.OrderArticles).Cast()
.Select(orderarticle => new
{
root.system.created,
root.system.by,
root.location.id,
order.OrderID,
order.OrderName,
orderarticle.Size,
orderarticle.ProductName,
orderarticle.ProductId,
})
)
)
);
}
}
Console.WriteLine(csv.ToString());
}
Fiddle示例:C# Online Compiler | .NET Fiddle
3.5 使用选择该方法展示了如何使用选择方法结合展平节点将JSON文件转换为CSV文件。您可能知道,JSON是一种分层的、关系的和结构化的数据,而CSV不是。如果您有从JSON读取器以分层格式生成的对象,则必须使用FlattenNode为true展平,然后选择所需的节点以生成输出。下面的示例显示了如何做到这一点。
清单 3.5.1 使用Selection将JSON转换为CSV文件
private static void UsingSelection()
{
StringBuilder csv = new StringBuilder();
using (var r = new ChoJSONReader("sample55.json")
.WithField("created", jsonPath: "$..system.created", isArray: false)
.WithField("by", jsonPath: "$..system.by", isArray: false)
.WithField("id", jsonPath: "$..location.id", isArray: false)
.WithField("country", jsonPath: "$..location.country", isArray: false)
.WithField("OrderID")
.WithField("OrderName")
.WithField("Size")
.WithField("ProductName")
.WithField("ProductId")
.Configure(c => c.FlattenNode = true)
.JsonSerializationSettings(s => s.DateParseHandling = DateParseHandling.None)
)
{
using (var w = new ChoCSVWriter(csv)
.WithDelimiter(";")
.WithFirstLineHeader())
{
w.Write(r);
}
}
Console.WriteLine(csv.ToString());
}
Fiddle示例:C# Online Compiler | .NET Fiddle
https://www.codeproject.com/Tips/5312218/Cinchoo-ETL-Converting-Complex-Nested-JSON-to-CSV