在 c# 中解析 json 文件以进入所有部分和属性
Parsing json file in c# to get into all sections and properties
==========更新
因此,在尝试正确表达问题时,我误导了响应者,没有给我我需要的答案。抱歉,让我试着澄清一下。
我需要能够循环浏览一个 json 文件,该文件不像我在 OP 中指出的那样结构化,它更加随机。 OP 文件没有很好地传达这一点。
让我尝试描述更接近我将要获取的文件的内容。前两个级别将是固定的,我将它们称为 LevelA 和 LevelB。但是 LevelB 中的属性可以是任意一对随机数据。这是一个更好的 json 文件示例:
{
"LevelA": {
"LevelB": [
{
"EmpName": "John",
"EmpGender": "Male",
"Age": "25"
},
{
"FavoriteFood": "Beer",
"BaseballTeam": "Kansas City Royals"
},
{
"Red": "10",
"Blue": "40",
"White: "True"
}
]
}
}
假设我需要写出以下内容给控制台:
A LevelB entry has these properties:
Property: EmpName, Value: John
Property: EmpGender, Value: Male
Property: Age, Value: 25
A LevelB entry has these properties:
Property: FavoriteFood, Value: Beer
Property: BaseballTeam, Value: Kansas City Royals
A LevelB entry has these properties:
Property: Red, Value: 10
Property: Blue, Value: 40
Property: White, Value: True
这可能没有意义,但是,我需要找到一种方法来做到这一点,我需要这些知识。我很欣赏关于使用模型的答案,但我没有看到一种使用模型的方法,而不会使我认为应该是一项简单的任务复杂化。虽然显然不够简单,但我无法弄清楚。 :)
==========
C#、VS 2019、.NET 框架控制台测试应用程序。我想做一些简单的事情,但找不到正确的语法。
我有一个具有以下结构的 json 文件。我想遍历下面的每个员工并获取其属性(姓名、性别等...):
{
"Company": {
"Employees": [
{
"EmpName": "John",
"EmpGender": "Male",
"Age": "25"
},
{
"EmpName": "Mary",
"EmpGender": "Female"
},
{
"EmpName": "Bill",
"Age": "30"
}
]
}
}
第一个问题是哪个包可以完成这项工作?我已经安装了 Microsoft.Extensions.Configuration.Json 和 System.Configuration.ConfigurationManager,但我很难正确地使用语法。这些包是否适合使用?我决定使用它们,因为我认为我可以通过 ConfigurationBuilder 加载文件,并且 GetSection and/or GetChildren 方法会帮助我。我可以加载文件,但我不知道如何使用这些方法来满足我的需求。
其次,我不想为此建立模型,我只想要数据。如果我可以将每个员工都放入字典中,我可以对其进行分析,这会让我继续前进。感谢您的任何建议。
你可以在.net core
中使用built-in JSON library
using System.Text.Json;
添加以下模型定义
public class Rootobject
{
public Company Company { get; set; }
}
public class Company
{
public Employee[] Employees { get; set; }
}
public class Employee
{
public string EmpName { get; set; }
public string EmpGender { get; set; }
public string Age { get; set; }
}
像下面这样反序列化你的对象
string jsonData = File.ReadAllText("data.json");
Rootobject ob = JsonSerializer.Deserialize<Rootobject>(jsonData);
现在你有 ob
在你的 C# 中将你的 JSON 表示为 C# 对象
I don't want to build a model for this
如果您使用 Visual Studio,您可以自动生成您的 JSON 所需的模型 类,如所述 here 以上模型由 [=27= 自动生成]
为什么要求不建模型?在我看来,这是最简单的方法,如果由于 JSON 更改而需要扩展,您可以轻松地在代码中进行调整。我在这里粘贴了一个使用 System.Text.Json 命名空间的示例代码(由于它是内置的,因此不需要其他包)。
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace jsontest
{
class Program
{
static void Main(string[] args)
{
string input = "{ \"Company\": { \"Employees\": [{ \"EmpName\": \"John\", \"EmpGender\": \"Male\", \"Age\": \"25\" }, { \"EmpName\": \"Mary\", \"EmpGender\": \"Female\" }, { \"EmpName\": \"Bill\", \"Age\": \"30\" }]}}";
var processedInput = JsonSerializer.Deserialize<Company>(input);
foreach (var item in processedInput.Peoples.PeopleList)
{
Console.WriteLine($"{item.Name} - {item.Gender} - {item.Age}");
}
}
}
public class Employee
{
[JsonPropertyName("EmpName")]
public string Name { get; set; }
[JsonPropertyName("EmpGender")]
public string Gender { get; set; }
[JsonPropertyName("Age")]
public string Age { get; set; }
}
public class Employees
{
[JsonPropertyName("Employees")]
public List<Employee> PeopleList { get; set; }
}
public class Company
{
[JsonPropertyName("Company")]
public Employees Peoples { get; set; }
}
}
更新后更新:
奇怪为什么要这样把数据存到JSON里。我写了一个快速代码,它使用正则表达式和一些内置函数来解析文本。最终结果与您希望的相似。代码有点长,只是为了方便大家理解,我加了一些注释。
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace jsontest
{
class Program
{
static void Main(string[] args)
{
List<List<ListItem>> result = new List<List<ListItem>>();
string input = "{ \"Company\": { \"Employees\": [{ \"EmpName\": \"John\", \"EmpGender\": \"Male\", \"Age\": \"25\" }, { \"EmpName\": \"Mary\", \"EmpGender\": \"Female\" }, { \"EmpName\": \"Bill\", \"Age\": \"30\" }]}}";
// Remove new lines, so input will become one single line
input = input.Replace(Environment.NewLine, " ");
// 1. group is the group name (in this case Employees)
// 2. group is the content after group name
string pattern1 = @"[{].+[{](.+)[\[](.+)[\]]";
foreach (System.Text.RegularExpressions.Match m in System.Text.RegularExpressions.Regex.Matches(input, pattern1))
{
// groupName -> "Employees":
string groupName = m.Groups[1].Value;
// groupName -> Employees
groupName = groupName.Substring(0, groupName.LastIndexOf("\""));
groupName = groupName.Substring(groupName.IndexOf("\"") + 1);
// contentList -> { "EmpName": "John", "EmpGender": "Male", "Age": "25" }, { "EmpName": "Mary", "EmpGender": "Female" }, { "EmpName": "Bill", "Age": "30" }
string contentList = m.Groups[2].Value;
// Split the line onto more lines where "}," characters
// { "EmpName": "John", "EmpGender": "Male", "Age": "25"
// { "EmpName": "Mary", "EmpGender": "Female"
// { "EmpName": "Bill", "Age": "30" }
string[] contentItems = contentList.Split("},");
foreach (var item in contentItems)
{
// Check every group and store them in separate list
result.Add(new List<ListItem>());
string[] keys = item.Split(",");
foreach (var key in keys)
{
// Check every Key-Value pair and store their value in the current list
string pattern2 = "[\"](.+)[:].[\"](.+)[\"]";
foreach (System.Text.RegularExpressions.Match m2 in System.Text.RegularExpressions.Regex.Matches(key, pattern2))
{
result[result.Count - 1].Add(new ListItem() { Property = groupName, Key = m2.Groups[1].Value.Substring(0, m2.Groups[1].Value.Length - 1), Value = m2.Groups[2].Value });
}
}
}
}
for (int i = 0; i < result.Count; i++)
{
for (int j = 0; j < result[i].Count; j++)
{
if (j == 0)
Console.WriteLine($"A {result[i][j].Property} entry has these properties:");
Console.WriteLine($"Proprty: {result[i][j].Key}, Value: {result[i][j].Value}");
}
}
}
}
class ListItem
{
public string Property { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
}
这段代码的输出是:
A Employees entry has these properties:
Proprty: EmpName, Value: John
Proprty: EmpGender, Value: Male
Proprty: Age, Value: 25
A Employees entry has these properties:
Proprty: EmpName, Value: Mary
Proprty: EmpGender, Value: Female
A Employees entry has these properties:
Proprty: EmpName, Value: Bill
Proprty: Age, Value: 30
如果你不想创建模型,而得到一个List<Dictionary<string,string>>
,你可以使用自定义模型绑定,这里是一个演示:
自定义绑定器:
public class CustomBinder:IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model = new List<Dictionary<string, string>>();
using (var reader = new StreamReader(bindingContext.HttpContext.Request.Body))
{
var body = reader.ReadToEndAsync();
var mydata = JsonConvert.DeserializeObject<JObject>(body.Result);
var s = mydata["Company"]["Employees"].ToString();
var list=JsonConvert.DeserializeObject<List<JObject>>(s);
foreach (var jobj in list) {
Dictionary<string, string> d = new Dictionary<string, string>();
foreach (var x in jobj)
{
string name = x.Key;
string value = x.Value.ToString();
d.Add(x.Key, x.Value.ToString());
}
model.Add(d);
}
}
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
操作:
public void TestJson1([ModelBinder(BinderType = typeof(CustomBinder))] List<Dictionary<string, string>> jsondata)
{
}
结果:
==========更新
因此,在尝试正确表达问题时,我误导了响应者,没有给我我需要的答案。抱歉,让我试着澄清一下。
我需要能够循环浏览一个 json 文件,该文件不像我在 OP 中指出的那样结构化,它更加随机。 OP 文件没有很好地传达这一点。
让我尝试描述更接近我将要获取的文件的内容。前两个级别将是固定的,我将它们称为 LevelA 和 LevelB。但是 LevelB 中的属性可以是任意一对随机数据。这是一个更好的 json 文件示例:
{
"LevelA": {
"LevelB": [
{
"EmpName": "John",
"EmpGender": "Male",
"Age": "25"
},
{
"FavoriteFood": "Beer",
"BaseballTeam": "Kansas City Royals"
},
{
"Red": "10",
"Blue": "40",
"White: "True"
}
]
}
}
假设我需要写出以下内容给控制台:
A LevelB entry has these properties:
Property: EmpName, Value: John
Property: EmpGender, Value: Male
Property: Age, Value: 25
A LevelB entry has these properties:
Property: FavoriteFood, Value: Beer
Property: BaseballTeam, Value: Kansas City Royals
A LevelB entry has these properties:
Property: Red, Value: 10
Property: Blue, Value: 40
Property: White, Value: True
这可能没有意义,但是,我需要找到一种方法来做到这一点,我需要这些知识。我很欣赏关于使用模型的答案,但我没有看到一种使用模型的方法,而不会使我认为应该是一项简单的任务复杂化。虽然显然不够简单,但我无法弄清楚。 :)
==========
C#、VS 2019、.NET 框架控制台测试应用程序。我想做一些简单的事情,但找不到正确的语法。 我有一个具有以下结构的 json 文件。我想遍历下面的每个员工并获取其属性(姓名、性别等...):
{
"Company": {
"Employees": [
{
"EmpName": "John",
"EmpGender": "Male",
"Age": "25"
},
{
"EmpName": "Mary",
"EmpGender": "Female"
},
{
"EmpName": "Bill",
"Age": "30"
}
]
}
}
第一个问题是哪个包可以完成这项工作?我已经安装了 Microsoft.Extensions.Configuration.Json 和 System.Configuration.ConfigurationManager,但我很难正确地使用语法。这些包是否适合使用?我决定使用它们,因为我认为我可以通过 ConfigurationBuilder 加载文件,并且 GetSection and/or GetChildren 方法会帮助我。我可以加载文件,但我不知道如何使用这些方法来满足我的需求。
其次,我不想为此建立模型,我只想要数据。如果我可以将每个员工都放入字典中,我可以对其进行分析,这会让我继续前进。感谢您的任何建议。
你可以在.net core
中使用built-in JSON libraryusing System.Text.Json;
添加以下模型定义
public class Rootobject
{
public Company Company { get; set; }
}
public class Company
{
public Employee[] Employees { get; set; }
}
public class Employee
{
public string EmpName { get; set; }
public string EmpGender { get; set; }
public string Age { get; set; }
}
像下面这样反序列化你的对象
string jsonData = File.ReadAllText("data.json");
Rootobject ob = JsonSerializer.Deserialize<Rootobject>(jsonData);
现在你有 ob
在你的 C# 中将你的 JSON 表示为 C# 对象
I don't want to build a model for this
如果您使用 Visual Studio,您可以自动生成您的 JSON 所需的模型 类,如所述 here 以上模型由 [=27= 自动生成]
为什么要求不建模型?在我看来,这是最简单的方法,如果由于 JSON 更改而需要扩展,您可以轻松地在代码中进行调整。我在这里粘贴了一个使用 System.Text.Json 命名空间的示例代码(由于它是内置的,因此不需要其他包)。
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace jsontest
{
class Program
{
static void Main(string[] args)
{
string input = "{ \"Company\": { \"Employees\": [{ \"EmpName\": \"John\", \"EmpGender\": \"Male\", \"Age\": \"25\" }, { \"EmpName\": \"Mary\", \"EmpGender\": \"Female\" }, { \"EmpName\": \"Bill\", \"Age\": \"30\" }]}}";
var processedInput = JsonSerializer.Deserialize<Company>(input);
foreach (var item in processedInput.Peoples.PeopleList)
{
Console.WriteLine($"{item.Name} - {item.Gender} - {item.Age}");
}
}
}
public class Employee
{
[JsonPropertyName("EmpName")]
public string Name { get; set; }
[JsonPropertyName("EmpGender")]
public string Gender { get; set; }
[JsonPropertyName("Age")]
public string Age { get; set; }
}
public class Employees
{
[JsonPropertyName("Employees")]
public List<Employee> PeopleList { get; set; }
}
public class Company
{
[JsonPropertyName("Company")]
public Employees Peoples { get; set; }
}
}
更新后更新: 奇怪为什么要这样把数据存到JSON里。我写了一个快速代码,它使用正则表达式和一些内置函数来解析文本。最终结果与您希望的相似。代码有点长,只是为了方便大家理解,我加了一些注释。
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace jsontest
{
class Program
{
static void Main(string[] args)
{
List<List<ListItem>> result = new List<List<ListItem>>();
string input = "{ \"Company\": { \"Employees\": [{ \"EmpName\": \"John\", \"EmpGender\": \"Male\", \"Age\": \"25\" }, { \"EmpName\": \"Mary\", \"EmpGender\": \"Female\" }, { \"EmpName\": \"Bill\", \"Age\": \"30\" }]}}";
// Remove new lines, so input will become one single line
input = input.Replace(Environment.NewLine, " ");
// 1. group is the group name (in this case Employees)
// 2. group is the content after group name
string pattern1 = @"[{].+[{](.+)[\[](.+)[\]]";
foreach (System.Text.RegularExpressions.Match m in System.Text.RegularExpressions.Regex.Matches(input, pattern1))
{
// groupName -> "Employees":
string groupName = m.Groups[1].Value;
// groupName -> Employees
groupName = groupName.Substring(0, groupName.LastIndexOf("\""));
groupName = groupName.Substring(groupName.IndexOf("\"") + 1);
// contentList -> { "EmpName": "John", "EmpGender": "Male", "Age": "25" }, { "EmpName": "Mary", "EmpGender": "Female" }, { "EmpName": "Bill", "Age": "30" }
string contentList = m.Groups[2].Value;
// Split the line onto more lines where "}," characters
// { "EmpName": "John", "EmpGender": "Male", "Age": "25"
// { "EmpName": "Mary", "EmpGender": "Female"
// { "EmpName": "Bill", "Age": "30" }
string[] contentItems = contentList.Split("},");
foreach (var item in contentItems)
{
// Check every group and store them in separate list
result.Add(new List<ListItem>());
string[] keys = item.Split(",");
foreach (var key in keys)
{
// Check every Key-Value pair and store their value in the current list
string pattern2 = "[\"](.+)[:].[\"](.+)[\"]";
foreach (System.Text.RegularExpressions.Match m2 in System.Text.RegularExpressions.Regex.Matches(key, pattern2))
{
result[result.Count - 1].Add(new ListItem() { Property = groupName, Key = m2.Groups[1].Value.Substring(0, m2.Groups[1].Value.Length - 1), Value = m2.Groups[2].Value });
}
}
}
}
for (int i = 0; i < result.Count; i++)
{
for (int j = 0; j < result[i].Count; j++)
{
if (j == 0)
Console.WriteLine($"A {result[i][j].Property} entry has these properties:");
Console.WriteLine($"Proprty: {result[i][j].Key}, Value: {result[i][j].Value}");
}
}
}
}
class ListItem
{
public string Property { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
}
这段代码的输出是:
A Employees entry has these properties:
Proprty: EmpName, Value: John
Proprty: EmpGender, Value: Male
Proprty: Age, Value: 25
A Employees entry has these properties:
Proprty: EmpName, Value: Mary
Proprty: EmpGender, Value: Female
A Employees entry has these properties:
Proprty: EmpName, Value: Bill
Proprty: Age, Value: 30
如果你不想创建模型,而得到一个List<Dictionary<string,string>>
,你可以使用自定义模型绑定,这里是一个演示:
自定义绑定器:
public class CustomBinder:IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model = new List<Dictionary<string, string>>();
using (var reader = new StreamReader(bindingContext.HttpContext.Request.Body))
{
var body = reader.ReadToEndAsync();
var mydata = JsonConvert.DeserializeObject<JObject>(body.Result);
var s = mydata["Company"]["Employees"].ToString();
var list=JsonConvert.DeserializeObject<List<JObject>>(s);
foreach (var jobj in list) {
Dictionary<string, string> d = new Dictionary<string, string>();
foreach (var x in jobj)
{
string name = x.Key;
string value = x.Value.ToString();
d.Add(x.Key, x.Value.ToString());
}
model.Add(d);
}
}
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
操作:
public void TestJson1([ModelBinder(BinderType = typeof(CustomBinder))] List<Dictionary<string, string>> jsondata)
{
}
结果: