将 JSON 个数组值合并到单个 CSV 列中
Merge JSON Array values into a single CSV column
我有一个 JSON 文件是这样的:
{
"id": 2,
"name": "I.1.A.2",
"activeFlag": true,
"recipients": [
{
"id": 3,
"identityName": "idenity1",
"fullName": "FullName1"
},
{
"id": 4,
"identityName": "identity2",
"fullName": "FullName2"
}
]
}
我需要使用 C# 和 dotnet Core 将其转换为类似于此的 CSV 输出。
"id","name","activeFlag","identityName"
"2","I.1.A.2","true","identity1;identity2"
但是,我只能将 CSV 输出为:
"id","name","activeFlag","recipients_0", "recipients_1"
"2","I.1.A.2","true","identity1","identity2"
这是生成上述输出的代码:
using (var csv = new ChoCSVWriter(".\temp\csvoutput.csv").WithFirstLineHeader()
)
{
using (var json = new ChoJSONReader(".\temp\tmpjson.json")
.Configure(c => c.ConvertToFlattenObject(arrayIndexSeparator: ';'))
.Configure(c => c.ArrayValueSeparator = ';')
.Configure(c => c.ArrayValueSeparator = ';')
.WithField("id", jsonPath: "$..id", isArray: false)
.WithField("recipients", jsonPath: "$..recipients[*]..identityName", isArray: true, fieldName: "recipients")
)
{
csv.Write(json);
}
}
现在,我正在使用 ChoEtl 库,但对其他 options/suggestions 开放。一直在寻找这个问题的答案,但还没有找到。对不起,如果我还没有找到一些解决方案。我确实在这里尝试了类似的解决方案: 但并没有完全满足我的需求。
就个人而言,我发现“投影”方法比基于配置的方法更易于使用和推理。参见 https://www.codeproject.com/Articles/1193650/Cinchoo-ETL-Quick-Start-Converting-JSON-to-CSV-Fil
这对我有用:
using (var csv = new ChoCSVWriter(output).WithFirstLineHeader()) {
using (var json = new ChoJSONReader(input))
{
csv.Write(json.Select(jsonItem =>
{
var recipientList = new List<dynamic>(jsonItem.recipients);
string recipientString = string.Join(';', recipientList.Select(r => r.identityName));
return new
{
id = jsonItem.id,
name = jsonItem.name,
activeFlag = jsonItem.activeFlag,
identityName = recipientString
};
}));
}
}
可能有更优雅的方法来构造 identityName
的值,但由于值是动态的,因此很难直接使用 Linq 而不会 运行 出现 CS1977 错误。
但是,如果您更喜欢基于配置的方法,则可以将 valueConverter
与 jsonPath
结合使用,如下所示:
using (var csv = new ChoCSVWriter(output).WithFirstLineHeader())
{
using (var json = new ChoJSONReader(input)
.WithField("id")
.WithField("name")
.WithField("activeFlag")
.WithField("recipients", jsonPath: "$.recipients[*].identityName"
, valueConverter: o => string.Join(';', ((object[])o).Select(x => x.ToString())))
)
{
csv.Write(json);
}
}
我找不到 ConvertToFlattenObject
的任何文档,所以我不确定它应该如何工作。
以上@Jack.A 的回答涵盖了产生预期输出的场景。
这是另一种方法,通过在 CSV 编写器中将 UseNestedKeyFormat
设置为 false
来生成预期的 CSV 输出
string json = @"
{
""id"": 2,
""name"": ""I.1.A.2"",
""activeFlag"": true,
""recipients"": [
{
""id"": 3,
""identityName"": ""idenity1"",
""fullName"": ""FullName1""
},
{
""id"": 4,
""identityName"": ""identity2"",
""fullName"": ""FullName2""
}
]
}";
StringBuilder csv = new StringBuilder();
using (var r = ChoJSONReader.LoadText(json)
.WithField("id")
.WithField("name")
.WithField("activeFlag")
.WithField("recipients", jsonPath: "$..recipients[*]..identityName")
)
{
using (var w = new ChoCSVWriter(csv)
.Configure(c => c.ArrayValueSeparator = ';')
.WithFirstLineHeader()
.QuoteAllFields()
.UseNestedKeyFormat(false)
)
{
w.Write(r);
}
}
Console.WriteLine(csv.ToString());
输出:
id,name,activeFlag,recipients
"2","I.1.A.2","True","idenity1,identity2"
示例 fiddle:https://dotnetfiddle.net/O1fKQA
我有一个 JSON 文件是这样的:
{
"id": 2,
"name": "I.1.A.2",
"activeFlag": true,
"recipients": [
{
"id": 3,
"identityName": "idenity1",
"fullName": "FullName1"
},
{
"id": 4,
"identityName": "identity2",
"fullName": "FullName2"
}
]
}
我需要使用 C# 和 dotnet Core 将其转换为类似于此的 CSV 输出。
"id","name","activeFlag","identityName"
"2","I.1.A.2","true","identity1;identity2"
但是,我只能将 CSV 输出为:
"id","name","activeFlag","recipients_0", "recipients_1"
"2","I.1.A.2","true","identity1","identity2"
这是生成上述输出的代码:
using (var csv = new ChoCSVWriter(".\temp\csvoutput.csv").WithFirstLineHeader()
)
{
using (var json = new ChoJSONReader(".\temp\tmpjson.json")
.Configure(c => c.ConvertToFlattenObject(arrayIndexSeparator: ';'))
.Configure(c => c.ArrayValueSeparator = ';')
.Configure(c => c.ArrayValueSeparator = ';')
.WithField("id", jsonPath: "$..id", isArray: false)
.WithField("recipients", jsonPath: "$..recipients[*]..identityName", isArray: true, fieldName: "recipients")
)
{
csv.Write(json);
}
}
现在,我正在使用 ChoEtl 库,但对其他 options/suggestions 开放。一直在寻找这个问题的答案,但还没有找到。对不起,如果我还没有找到一些解决方案。我确实在这里尝试了类似的解决方案:
就个人而言,我发现“投影”方法比基于配置的方法更易于使用和推理。参见 https://www.codeproject.com/Articles/1193650/Cinchoo-ETL-Quick-Start-Converting-JSON-to-CSV-Fil
这对我有用:
using (var csv = new ChoCSVWriter(output).WithFirstLineHeader()) {
using (var json = new ChoJSONReader(input))
{
csv.Write(json.Select(jsonItem =>
{
var recipientList = new List<dynamic>(jsonItem.recipients);
string recipientString = string.Join(';', recipientList.Select(r => r.identityName));
return new
{
id = jsonItem.id,
name = jsonItem.name,
activeFlag = jsonItem.activeFlag,
identityName = recipientString
};
}));
}
}
可能有更优雅的方法来构造 identityName
的值,但由于值是动态的,因此很难直接使用 Linq 而不会 运行 出现 CS1977 错误。
但是,如果您更喜欢基于配置的方法,则可以将 valueConverter
与 jsonPath
结合使用,如下所示:
using (var csv = new ChoCSVWriter(output).WithFirstLineHeader())
{
using (var json = new ChoJSONReader(input)
.WithField("id")
.WithField("name")
.WithField("activeFlag")
.WithField("recipients", jsonPath: "$.recipients[*].identityName"
, valueConverter: o => string.Join(';', ((object[])o).Select(x => x.ToString())))
)
{
csv.Write(json);
}
}
我找不到 ConvertToFlattenObject
的任何文档,所以我不确定它应该如何工作。
以上@Jack.A 的回答涵盖了产生预期输出的场景。
这是另一种方法,通过在 CSV 编写器中将 UseNestedKeyFormat
设置为 false
来生成预期的 CSV 输出
string json = @"
{
""id"": 2,
""name"": ""I.1.A.2"",
""activeFlag"": true,
""recipients"": [
{
""id"": 3,
""identityName"": ""idenity1"",
""fullName"": ""FullName1""
},
{
""id"": 4,
""identityName"": ""identity2"",
""fullName"": ""FullName2""
}
]
}";
StringBuilder csv = new StringBuilder();
using (var r = ChoJSONReader.LoadText(json)
.WithField("id")
.WithField("name")
.WithField("activeFlag")
.WithField("recipients", jsonPath: "$..recipients[*]..identityName")
)
{
using (var w = new ChoCSVWriter(csv)
.Configure(c => c.ArrayValueSeparator = ';')
.WithFirstLineHeader()
.QuoteAllFields()
.UseNestedKeyFormat(false)
)
{
w.Write(r);
}
}
Console.WriteLine(csv.ToString());
输出:
id,name,activeFlag,recipients
"2","I.1.A.2","True","idenity1,identity2"
示例 fiddle:https://dotnetfiddle.net/O1fKQA