从 C# 中的 JSON 对象中提取数组(新
Posted
技术标签:
【中文标题】从 C# 中的 JSON 对象中提取数组(新【英文标题】:Pulling an Array from a JSON object in C# (New 【发布时间】:2020-05-23 18:28:37 【问题描述】:我在 C# 中使用 Newtonsoft JSON。
我有一个正在尝试解析的日志文件,以便我可以使用日志文件中的数据填充数据库。
在日志文件中,每一行都是一个单独的 JSON 对象。
日志文件如下所示:
"timestamp":"2020-02-02T04:49:53Z", "event":"Friends", "Status":"Online", "Name":"User1"
"timestamp":"2020-02-02T04:48:06Z", "event":"Commander", "FID":"F2", "Name":"User2"
"timestamp":"2020-02-02T04:48:06Z", "event":"Materials", "Raw":[ "Name":"cadmium", "Count":9,
"Name":"zinc", "Count":45 , "Name":"iron", "Count":71 ]
这是我目前正在做的事情:
var fullPath = @"X:\Data\Log Files\test log.log";
string[] lines = File.ReadAllLines(fullPath);
foreach (var line in lines)
var json = JObject.Parse(line);
var eventType = json["event"].Value<string>();
JArray raw = (JArray)line["Raw"];
switch (eventType)
case "Friends":
var status = json["Status"].Value<string>();
var frName = json["Name"].Value<string>();
Console.WriteLine("The friend " + frName + " is currently " + status + ".");
Console.WriteLine(json);
break;
case "Commander":
var fid = json["FID"].Value<string>();
var CMDR = json["Name"].Value<string>();
Console.WriteLine("User " + CMDR + " with ID " + ".");
Console.WriteLine(json);
break;
case "Materials":
//do something here that is magical.
break;
default:
Console.WriteLine("N/A");
break;
前两种情况正常。但是,我不知道如何从“材料”事件中获取数组“原始”。
仅供参考 - 该行中还有另外两个数组。所以,我需要能够 提取“Raw”以及其他数组。
到目前为止,我只是想不通。
我是一个初学者,所以请像在和蹒跚学步的孩子说话一样解释这一点。 :)
请帮忙?
非常感谢!
【问题讨论】:
试试看这个 SO:***.com/questions/15184430/… 【参考方案1】:以上所有答案对于您提出的问题都是完全有效的,但是,为了更好的代码可读性和调试,您最好将这些 json 字符串转换为实际的 c# 对象。例如,您会设置一些这样的模型:
public class Friends
public string Timestamp get; set;
public string Event get; set;
public string Status get; set;
public string Name get; set;
public class Commander
public string Timestamp get; set;
public string Event get; set;
public string FID get; set;
public string Name get; set;
public class Materials
public string Timestamp get; set;
public string Event get; set;
public List<Material> Raw get; set;
public class Material
public string Name get; set;
public string Count get; set;
每个不同的日志类型都有 1 个模型。现在,在您的逻辑中,您要做的是从 JSON 中读取事件类型,然后将其转换为有效的 c# 类型(在下面的代码中,我使用字典),然后使用该类型告诉 JsonConvert.DeserializeObject 方法要做什么将您的 json 字符串转换为,这就是我实现它的方式:
//Same as your code
var fullPath = @"C:\testLog.log";
string[] lines = File.ReadAllLines(fullPath);
//This dictionary stores each of your different log types in a way where you can use the "event" string in each json to get the c# object type
Dictionary<string, Type> types = new Dictionary<string, Type>()
"Friends", typeof(Friends),
"Commander", typeof(Commander) ,
"Materials", typeof(Materials)
;
foreach (var line in lines)
//Same as your code
var json = JObject.Parse(line);
Type eventType = types[json["event"].Value<string>()];
//This line will use the event type provided by the json to deserialise your object
var x = JsonConvert.DeserializeObject(line, eventType);
switch (x)
case Friends friendObject:
//Do stuff with the friend object here
Console.WriteLine("Friend log found");
Console.WriteLine(friendObject.Timestamp);
Console.WriteLine(friendObject.Name);
Console.WriteLine(friendObject.Status);
Console.WriteLine();
break;
case Commander commanderObject:
//Do stuff with the commander object here
Console.WriteLine("Commander log found");
Console.WriteLine(commanderObject.Timestamp);
Console.WriteLine(commanderObject.FID);
Console.WriteLine(commanderObject.Name);
Console.WriteLine();
break;
case Materials materialsObject:
//do stuff with the material object here
Console.WriteLine("Materials log found");
Console.WriteLine(materialsObject.Timestamp);
materialsObject.Raw.ForEach(material=>Console.WriteLine(material.Name + ". Count: " + material.Count));
break;
【讨论】:
【参考方案2】:您可以执行以下操作。
var eventType = json["event"].Value<string>();
Console.WriteLine($"Event Type eventType");
foreach(var obj in json["Raw"])
Console.WriteLine($"Name=obj["Name"],Count = obj["Count"]");
在这种情况下,您从 Json 对象中解析“原始”数组并遍历 JObject 以获取数组中的每个元素
【讨论】:
【参考方案3】:你需要解析一个 JToken 数组。 请试试这个:
foreach (var line in lines)
var json = JObject.Parse(line);
var eventType = json["event"].Value<string>();
switch (eventType)
case "Friends":
var status = json["Status"].Value<string>();
var frName = json["Name"].Value<string>();
Console.WriteLine("The friend " + frName + " is currently " + status + ".");
Console.WriteLine(json);
break;
case "Commander":
var fid = json["FID"].Value<string>();
var CMDR = json["Name"].Value<string>();
Console.WriteLine("User " + CMDR + " with ID " + ".");
Console.WriteLine(json);
break;
case "Materials":
var raw = JArray.Parse(json["Raw"].ToString());
foreach(JToken token in raw)
Console.WriteLine("Name " + token["Name"] + " Counter " + token["Count"]);
break;
default:
Console.WriteLine("N/A");
break;
希望对你有所帮助。
【讨论】:
【参考方案4】:我建议不要逐行,而是 ReadAllText
并循环 JsonArray
var json = JArray.Parse(File.ReadAllText(fullPath));
foreach (var jsonItem in json)
var eventType = jsonItem["event"].ToString();
switch (eventType)
case "Friends":
var status = jsonItem["Status"].Value<string>();
var frName = jsonItem["Name"].Value<string>();
Console.WriteLine("The friend " + frName + " is currently " + status + ".");
break;
case "Commander":
var fid = jsonItem["FID"].Value<string>();
var CMDR = jsonItem["Name"].Value<string>();
Console.WriteLine("User " + CMDR + " with ID " + ".");
break;
case "Materials":
//Your magic code here
var raw = JArray.Parse(jsonItem["Raw"].ToString());
foreach (var rawItem in raw)
Console.WriteLine("Name " + rawItem["Name"] + " with Count " + rawItem["Count"] + ".");
break;
default:
Console.WriteLine("N/A");
break;
【讨论】:
【参考方案5】:谢谢大家的回答。
我最终做了一些接近咖啡建议的事情。
首先,我在我的解决方案中添加了一个类文件。然后,复制 JSON 字符串并执行“Edit>Paste Special>Paste JSON as Classes”创建了这个:
public class Materials
public DateTime timestamp get; set;
public string _event get; set;
public Raw[] Raw get; set;
public class Raw
public string Name get; set;
public int Count get; set;
然后,我将对象反序列化为一个列表:
case "Materials":
//do something here that is magical.
Materials m = JsonConvert.DeserializeObject<Materials>(line);
List<Raw> r = m.Raw.ToList();
break;
这似乎起到了作用。大家觉得呢?
【讨论】:
看起来不错,我绝对建议您对所有日志执行此操作,以便将来假设您想向其中一个日志添加额外的属性,您可以将其添加到类中并就是这样,无需手动编写代码来获取数据以上是关于从 C# 中的 JSON 对象中提取数组(新的主要内容,如果未能解决你的问题,请参考以下文章
C# JSON 反序列化:如何从 JSON 对象数组中获取值 [重复]