gpt4 book ai didi

c# - 从 JSON 文件在 C# 中创建一个类

转载 作者:行者123 更新时间:2023-12-04 10:48:35 26 4
gpt4 key购买 nike

我对 C# 很陌生,尽管几年前我已经涉足过 VB。

我创建了一个带有多行文本框的基本 Windows 窗体,并将文本文件的内容写入文本框:

public Form1()
{
InitializeComponent();

List<string> lines = File.ReadAllLines(@"X:\Log Files\01.log").ToList();

lines.ForEach(l => {

textBox1.AppendText(l);
textBox1.AppendText(Environment.NewLine);
});

}

我这样做是为了我可以看到我实际上正在阅读文件的内容。我知道……你们都对这种惊人的技能印象深刻。

因此,这里是文本文件中的一些行:
{ "timestamp":"2020-01-03T00:20:22Z", "event":"Rank", "Rank1":3, "Rank2":8 }
{ "timestamp":"2020-01-03T00:20:22Z", "event":"Progress", "Task1":56, "Task2":100 }
{ "timestamp":"2020-01-03T00:20:22Z", "event":"Reputation", "Nation":75.000000, "State":75.000000 }
{ "timestamp":"2020-01-03T00:20:27Z", "event":"Music", "MusicTrack":"NoTrack" }

我想根据事件类型创建对象。就像是:
   public Progress(int time, int t1, int t2)
{
this.timestamp = time; //'time' is the timestamp value from the line
this.task1 = t1; //'t1' is the Task1 value from the line
this.task2 = t2; //'t2' is the Task2 value from the line
}

读取文件时,需要 event字段并使用它来确定要实例化的类。 timestamp将保留该行,然后将每个事件的字段填充为类的属性。

我已经安装 Newtonsoft.Json进入 Visual Studio,我认为这本身就有能力做到这一点。

但是,我在文档中看不到如何执行此操作。

任何人都可以指出我正确的方向吗?

谢谢!!

最佳答案

此代码适用于我的机器。您需要为 .log 文件中的所有其他事件添加事件子类(派生自 BaseEvent 的那些,即 RankEvent ),并将属性添加到 JsonEvent这些的类并将值添加到 EventType并更新 switch statement .

我是如何做到的:

  • 我从您的 .log 文件中复制了每一行
  • IE。 { "timestamp":"2020-01-03T00:20:22Z", "event":"Rank", "Rank1":3, "Rank2":8 }
  • 我去了here并将该行粘贴到左侧窗口中以获得 C# 类,然后我创建了一个组合 JsonEvent从所有的行类。
  • 我做了 primitive types nullable因为在每次解析循环之后,某些属性将为空
  • 我做了一个基类 BaseEvent具有共同属性(在这种情况下只是 Timestamp )
  • 我做了 BaseEvent 的子类对于每个事件,即 RankEvent
  • 我做了一个事件枚举 EventType解析 "event"属性(property)。
  • 我遍历了所有行,对于每一行,我将行反序列化为 JsonEvent C# 类( jsonEvent )并查看 EventType知道我应该创建哪个子类。
  • 对于每个循环,我将一个子类( newEvent )解析/反序列化为一个列表 List<BaseEvent>事件列表
  • 循环完成后,eventList变量已填充并准备在程序的其余部分中使用。
  • using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.Serialization;

    namespace StackOverFlow
    {
    public class Program
    {
    static void Main(string[] args)
    {
    var file = @"X:\Log Files\01.log";
    var eventList = ParseEvents(file);
    //TODO Do something
    }

    private static List<BaseEvent> ParseEvents(string file)
    {
    //TODO Encapsulate in a try & catch and add a logger for error handling
    var eventList = new List<BaseEvent>();
    var lines = File.ReadAllLines(file).ToList();
    foreach (var line in lines)
    {
    var jsonEvent = JsonConvert.DeserializeObject<JsonEvent>(line);
    BaseEvent newEvent;
    switch (jsonEvent.EventType)
    {
    case EventType.Rank:
    newEvent = new RankEvent(jsonEvent);
    eventList.Add(newEvent);
    break;
    case EventType.Progress:
    newEvent = new ProgressEvent(jsonEvent);
    eventList.Add(newEvent);
    break;
    case EventType.Reputation:
    newEvent = new ReputationEvent(jsonEvent);
    eventList.Add(newEvent);
    break;
    case EventType.Music:
    newEvent = new MusicEvent(jsonEvent);
    eventList.Add(newEvent);
    break;

    //TODO Add more cases for each EventType

    default:
    throw new Exception(String.Format("Unknown EventType: {0}", jsonEvent.EventType));
    }
    }

    return eventList;
    }
    }

    //TODO Move classes/enums to a separate folder

    [JsonConverter(typeof(StringEnumConverter))]
    public enum EventType
    {
    [EnumMember(Value = "Rank")]
    Rank,
    [EnumMember(Value = "Progress")]
    Progress,
    [EnumMember(Value = "Reputation")]
    Reputation,
    [EnumMember(Value = "Music")]
    Music,

    //TODO Add more enum values for each "event"
    }

    public abstract class BaseEvent
    {
    public BaseEvent(DateTime timestamp)
    {
    Timestamp = timestamp;
    }
    public DateTime Timestamp { get; set; }
    }

    public class RankEvent : BaseEvent
    {
    public RankEvent(JsonEvent jsonEvent) : base(jsonEvent.Timestamp)
    {
    Rank1 = jsonEvent.Rank1.Value;
    Rank2 = jsonEvent.Rank2.Value;
    }
    public int Rank1 { get; set; }
    public int Rank2 { get; set; }
    }

    public class ProgressEvent : BaseEvent
    {
    public ProgressEvent(JsonEvent jsonEvent) : base(jsonEvent.Timestamp)
    {
    Task1 = jsonEvent.Task1.Value;
    Task2 = jsonEvent.Task2.Value;
    }
    public int Task1 { get; set; }
    public int Task2 { get; set; }
    }

    public class ReputationEvent : BaseEvent
    {
    public ReputationEvent(JsonEvent jsonEvent) : base(jsonEvent.Timestamp)
    {
    Nation = jsonEvent.Nation.Value;
    State = jsonEvent.State.Value;
    }
    public double Nation { get; set; }
    public double State { get; set; }
    }

    public class MusicEvent : BaseEvent
    {
    public MusicEvent(JsonEvent jsonEvent) : base(jsonEvent.Timestamp)
    {
    MusicTrack = jsonEvent.MusicTrack;
    }
    public string MusicTrack { get; set; }
    }

    //TODO Add more derived sub classes of the BaseEvent

    [JsonObject]
    public class JsonEvent
    {
    [JsonProperty("timestamp")]
    public DateTime Timestamp { get; set; }
    [JsonProperty("event")]
    public EventType EventType { get; set; }
    public int? Rank1 { get; set; }
    public int? Rank2 { get; set; }
    public int? Task1 { get; set; }
    public int? Task2 { get; set; }
    public double? Nation { get; set; }
    public double? State { get; set; }
    public string MusicTrack { get; set; }

    //TODO Add more properties
    }
    }

    eventList快速观看:
    enter image description here

    补充阅读:

    将 Json 解析为 C#

    How can I parse JSON with C#?

    https://www.jerriepelser.com/blog/deserialize-different-json-object-same-class/

    在 Visual Studio 中调试

    (总是用 F9 在一行上设置断点,然后按 F5 并用 F10/F11 单步执行代码,它可以深入了解代码的行为方式)

    https://docs.microsoft.com/en-us/visualstudio/debugger/navigating-through-code-with-the-debugger?view=vs-2019

    从 Json 创建 C# 类的工具:

    https://app.quicktype.io/#l=cs&r=json2csharp

    https://marketplace.visualstudio.com/items?itemName=DangKhuong.JSONtoC

    更新:
    我制作了一个额外的脚本,为您创建上述 C# 子类:


    只需运行这个脚本,所有的类(包括 Program.cs )都会被创建。
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;

    namespace CreateFiles
    {
    public class Program
    {
    static void Main(string[] args)
    {
    var file = @"X:\Log Files\01.log";
    var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
    //Change outPutPath to your choosing
    var outPutPath = Path.Combine(desktop, "Temp");
    //Change namespaceName to your choosing
    var namespaceName = "StackOverFlow";
    var uniqueList = GetUniqueEventTypeList(file);
    CreateBaseClass(outPutPath, namespaceName);
    CreateEventClasses(uniqueList, outPutPath, namespaceName);
    CreateEnumClass(uniqueList, outPutPath, namespaceName);
    CreateJsonEventClass(uniqueList, outPutPath, namespaceName);
    CreateProgramClass(uniqueList, outPutPath, namespaceName);
    Console.WriteLine($"\nParsing done! Classes parsed to {outPutPath}");
    Console.WriteLine("Press any key to continue.");
    Console.ReadLine();
    }

    private static List<string> GetUniqueEventTypeList(string file)
    {
    var lines = File.ReadAllLines(file).ToList();
    var uniqueEventTypes = new List<string>();
    var uniqueList = new List<string>();

    foreach (var line in lines)
    {
    var json = JObject.Parse(line);
    var eventType = json["event"].Value<string>();
    if (!uniqueEventTypes.Exists(e => e.Equals(eventType)))
    {
    uniqueEventTypes.Add(eventType);
    uniqueList.Add(line);
    }
    }
    return uniqueList;
    }

    private static void CreateEventClasses(List<string> lines, string path, string namespaceName)
    {
    foreach (var line in lines)
    {
    var jObj = JObject.Parse(line);
    CreateEventClass(jObj, path, namespaceName);
    }
    }

    public class ParseClass
    {
    public ParseClass(KeyValuePair<string, JToken> obj)
    {
    Name = obj.Key;
    SetType(obj.Value);
    }
    public string Name { get; set; }
    public string Type { get; set; }
    public bool IsPrimitive { get; set; }

    private void SetType(JToken token)
    {
    switch (token.Type)
    {
    case JTokenType.Integer:
    Type = "int";
    IsPrimitive = true;
    break;
    case JTokenType.Float:
    Type = "double";
    IsPrimitive = true;
    break;
    case JTokenType.String:
    Type = "string";
    IsPrimitive = false;
    break;
    case JTokenType.Boolean:
    Type = "bool";
    IsPrimitive = true;
    break;
    case JTokenType.Date:
    Type = "DateTime";
    IsPrimitive = true;
    break;
    case JTokenType.Guid:
    Type = "Guid";
    IsPrimitive = true;
    break;
    case JTokenType.Uri:
    Type = "Uri";
    IsPrimitive = false;
    break;
    default:
    throw new Exception($"Unknown type {token.Type}");
    }
    }
    }

    private static void CreateProgramClass(List<string> lines, string path, string namespaceName)
    {
    Directory.CreateDirectory(path);
    var className = "Program";
    var fileName = $"{className}.cs";
    var file = Path.Combine(path, fileName);

    try
    {
    // Create a new file
    using (FileStream fsStream = new FileStream(file, FileMode.Create))
    using (StreamWriter sw = new StreamWriter(fsStream, Encoding.UTF8))
    {
    //The Program class needed these bytes in the beginning to work
    sw.WriteLine("using Newtonsoft.Json;");
    sw.WriteLine("using System;");
    sw.WriteLine("using System.Collections.Generic;");
    sw.WriteLine("using System.IO;");
    sw.WriteLine("using System.Linq;");
    sw.WriteLine("");
    sw.WriteLine($"namespace {namespaceName}");
    sw.WriteLine("{");
    sw.WriteLine($" public class {className}");
    sw.WriteLine(" {");
    sw.WriteLine($" static void Main(string[] args)");
    sw.WriteLine(" {");
    sw.WriteLine(" var file = @\"X:\\Log Files\\01.log\";");
    sw.WriteLine(" var eventList = ParseEvents(file);");
    sw.WriteLine(" //TODO Do something");
    sw.WriteLine(" }");
    sw.WriteLine("");
    sw.WriteLine(" private static List<BaseEvent> ParseEvents(string file)");
    sw.WriteLine(" {");
    sw.WriteLine(" //TODO Encapsulate in a try & catch and add a logger for error handling");
    sw.WriteLine(" var eventList = new List<BaseEvent>();");
    sw.WriteLine(" var lines = File.ReadAllLines(file).ToList();");
    sw.WriteLine("");
    sw.WriteLine(" foreach (var line in lines)");
    sw.WriteLine(" {");
    sw.WriteLine(" var jsonEvent = JsonConvert.DeserializeObject<JsonEvent>(line);");
    sw.WriteLine(" BaseEvent newEvent;");
    sw.WriteLine(" switch (jsonEvent.EventType)");
    sw.WriteLine(" {");
    foreach (var line in lines)
    {
    var jObj = JObject.Parse(line);
    var eventType = jObj["event"].Value<string>();
    sw.WriteLine($" case EventType.{eventType}:");
    sw.WriteLine($" newEvent = new {eventType}Event(jsonEvent);");
    sw.WriteLine($" eventList.Add(newEvent);");
    sw.WriteLine($" break;");
    }
    sw.WriteLine(" default:");
    sw.WriteLine(" throw new Exception(String.Format(\"Unknown EventType: {0} \", jsonEvent.EventType));");
    sw.WriteLine(" }");
    sw.WriteLine(" }");
    sw.WriteLine(" return eventList;");
    sw.WriteLine(" }");
    sw.WriteLine(" }");
    sw.WriteLine("}");
    }
    Console.WriteLine($"Created {fileName}.");
    }
    catch (Exception Ex)
    {
    Console.WriteLine(Ex.ToString());
    }
    }

    private static void CreateEnumClass(List<string> lines, string path, string namespaceName)
    {
    Directory.CreateDirectory(Path.Combine(path));
    var className = "EventType";
    var fileName = $"{className}.cs";
    var file = Path.Combine(path, fileName);
    FileInfo fi = new FileInfo(file);

    try
    {
    // Check if file already exists. If yes, throw exception.
    if (fi.Exists)
    {
    throw new Exception($"{file} already exists!");
    }

    // Create a new file
    using (FileStream fsStream = new FileStream(file, FileMode.Create))
    using (StreamWriter sw = new StreamWriter(fsStream, Encoding.UTF8))
    {
    sw.WriteLine("using Newtonsoft.Json;");
    sw.WriteLine("using Newtonsoft.Json.Converters;");
    sw.WriteLine("using System.Runtime.Serialization;");
    sw.WriteLine("");
    sw.WriteLine($"namespace {namespaceName}");
    sw.WriteLine("{");
    sw.WriteLine($" [JsonConverter(typeof(StringEnumConverter))]");
    sw.WriteLine($" public enum {className}");
    sw.WriteLine(" {");
    foreach (var line in lines)
    {
    var jObj = JObject.Parse(line);
    var eventType = jObj["event"].Value<string>();
    sw.WriteLine($" [EnumMember(Value = \"{eventType}\")]");
    sw.WriteLine($" {eventType},");
    }
    sw.WriteLine(" }");
    sw.WriteLine("}");
    }
    Console.WriteLine($"Created {fileName}.");
    }
    catch (Exception Ex)
    {
    Console.WriteLine(Ex.ToString());
    }
    }

    private static void CreateJsonEventClass(List<string> lines, string path, string namespaceName)
    {

    Directory.CreateDirectory(path);
    var className = "JsonEvent";
    var fileName = $"{className}.cs";
    var file = Path.Combine(path, fileName);
    FileInfo fi = new FileInfo(file);

    var propertyList = new List<ParseClass>();
    foreach (var line in lines)
    {
    var jObject = JObject.Parse(line);
    foreach (var obj in jObject)
    {
    if (!(obj.Key.Equals("event") || obj.Key.Equals("timestamp")))
    {
    propertyList.Add(new ParseClass(obj));
    }
    }
    }

    try
    {
    // Check if file already exists. If yes, throw exception.
    if (fi.Exists)
    {
    throw new Exception($"{file} already exists!");
    }
    // Create a new file
    using (FileStream fsStream = new FileStream(file, FileMode.Create))
    using (StreamWriter sw = new StreamWriter(fsStream, Encoding.UTF8))
    {
    sw.WriteLine("using Newtonsoft.Json;");
    sw.WriteLine("using System;");
    sw.WriteLine("");
    sw.WriteLine($"namespace {namespaceName}");
    sw.WriteLine("{");
    sw.WriteLine($" [JsonObject]");
    sw.WriteLine($" public class {className}");
    sw.WriteLine("{");
    sw.WriteLine(" [JsonProperty(\"timestamp\")]");
    sw.WriteLine(" public DateTime Timestamp { get; set; }");
    sw.WriteLine(" [JsonProperty(\"event\")]");
    sw.WriteLine(" public EventType EventType { get; set; }");
    foreach (var property in propertyList)
    {
    var type = property.IsPrimitive ? property.Type + "?" : property.Type;
    sw.WriteLine(" public " + type + " " + property.Name + " { get; set; }");
    }
    sw.WriteLine(" }");
    sw.WriteLine("}");
    }
    Console.WriteLine($"Created {fileName}.");
    }
    catch (Exception Ex)
    {
    Console.WriteLine(Ex.ToString());
    }
    }

    private static void CreateBaseClass(string path, string namespaceName)
    {
    Directory.CreateDirectory(path);
    var className = $"BaseEvent";
    var fileName = $"{className}.cs";
    var file = Path.Combine(path, fileName);

    FileInfo fi = new FileInfo(file);

    try
    {
    // Check if file already exists. If yes, throw exception.
    if (fi.Exists)
    {
    throw new Exception($"{file} already exists!");
    }

    // Create a new file
    using (StreamWriter sw = fi.CreateText())
    {
    sw.WriteLine($"using System;");
    sw.WriteLine("");
    sw.WriteLine($"namespace {namespaceName}");
    sw.WriteLine("{");
    sw.WriteLine($" public abstract class BaseEvent");
    sw.WriteLine(" {");
    sw.WriteLine($" public BaseEvent(DateTime timestamp)");
    sw.WriteLine(" {");
    sw.WriteLine($" Timestamp = timestamp;");
    sw.WriteLine(" }");
    sw.WriteLine(" public DateTime Timestamp { get; set; }");
    sw.WriteLine(" }");
    sw.WriteLine("}");
    }
    Console.WriteLine($"Created {fileName}.");
    }
    catch (Exception Ex)
    {
    Console.WriteLine(Ex.ToString());
    }
    }

    private static void CreateEventClass(JObject jObject, string path, string namespaceName)
    {
    Directory.CreateDirectory(path);
    var eventName = $"{jObject["event"].Value<string>()}";
    var className = $"{eventName}Event";
    var fileName = $"{className}.cs";
    var file = Path.Combine(path, fileName);

    FileInfo fi = new FileInfo(file);

    var propertyList = new List<ParseClass>();
    foreach (var obj in jObject)
    {
    if (!(obj.Key.Equals("event") || obj.Key.Equals("timestamp")))
    {
    propertyList.Add(new ParseClass(obj));
    }
    }

    try
    {
    // Check if file already exists. If yes, throw exception.
    if (fi.Exists)
    {
    throw new Exception($"{file} already exists!");
    }

    // Create a new file
    using (FileStream fsStream = new FileStream(file, FileMode.Create))
    using (StreamWriter sw = new StreamWriter(fsStream, Encoding.UTF8))
    {
    sw.WriteLine($"namespace {namespaceName}");
    sw.WriteLine("{");
    sw.WriteLine($" public class {className} : BaseEvent");
    sw.WriteLine(" {");
    sw.WriteLine($" public {className}(JsonEvent jsonEvent) : base(jsonEvent.Timestamp)");
    sw.WriteLine(" {");
    foreach (var property in propertyList)
    {
    var name = property.IsPrimitive ? $"{property.Name}.Value" : $"{property.Name}";
    sw.WriteLine($" {property.Name} = jsonEvent.{name};");
    }
    sw.WriteLine(" }");
    foreach (var property in propertyList)
    {
    sw.WriteLine(" public " + property.Type + " " + property.Name + " { get; set; }");
    }
    sw.WriteLine(" }");
    sw.WriteLine("}");
    }
    Console.WriteLine($"Created {fileName}.");
    }
    catch (Exception Ex)
    {
    Console.WriteLine(Ex.ToString());
    }
    }
    }
    }

    关于c# - 从 JSON 文件在 C# 中创建一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59588372/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com