我正在try 用Utf 8 JsonReader i进行反序列化,因为它可以很容易地制作,但我需要进行自定义反序列化. 当我try 对其中包含对象的数组进行反序列化时,它会读取两次,如此屏幕截图所示:

Screen capture showing the file was read twice

我没有找到很多关于如何使用Utf 8 JsonReader的信息,所以也许我把这一切都搞砸了.

这是我的子化代码:

public Map? ReadYaml(string json)
{
    JsonReaderOptions options = new() { AllowTrailingCommas = true, CommentHandling = JsonCommentHandling.Skip };
    Utf8JsonReader reader = new(System.Text.Encoding.UTF8.GetBytes(json), options);

    Map map = new();

    while (reader.Read())
    {
        switch (reader.TokenType)
        {
            case JsonTokenType.PropertyName:
                if (reader.ValueTextEquals("Map name"))
                {
                    reader.Read();

                    map = new(reader.GetString());
                }
                if (reader.ValueTextEquals("Entities"))
                {
                    reader.Read();

                    if (reader.TokenType == JsonTokenType.StartArray)
                    {
                        while (reader.Read())
                        {
                            if (reader.TokenType == JsonTokenType.EndArray)
                                break;

                            if (reader.TokenType == JsonTokenType.StartObject)
                            {
                                while (reader.Read())
                                {
                                    if (reader.TokenType == JsonTokenType.EndObject)
                                        break;

                                    if (reader.TokenType == JsonTokenType.PropertyName)
                                    {
                                        reader.Read();
                                        if (reader.TokenType == JsonTokenType.String)
                                        {
                                            var str = reader.GetString();
                                            if (str != null)
                                            {
                                                Debug.Log(str);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
                break;
        }
    }
    return map;
}

这是我要反序列化的SON文件:


{
  "Map name": "NewMap",
  "Entities": [
    {
      "Name": "Entity",
      "Active": "True",
      "GUID": "f06ed7d3-f1b3-4cfd-a623-a7ceb17dbced"
    },
    {
      "Name": "Entity #1",
      "Active": "True",
      "GUID": "03788f46-e430-4882-a097-e860d2c7aed5"
    }
  ],
  "Entity components": [
    {
      "Component type": "ExtremeEngine.Transform",
      "Component data": [
        {
          "Position": null,
          "Rotation": null,
          "Scale": null,
          "Entity": "f06ed7d3-f1b3-4cfd-a623-a7ceb17dbced",
          "GUIHeaderIsOpened": "True",
          "Enabled": "True",
          "GUID": "95dea154-6f00-41b0-bdec-fe78cca589c3"
        }
      ]
    },
    {
      "Component type": "ExtremeEngine.Transform",
      "Component data": [
        {
          "Position": null,
          "Rotation": null,
          "Scale": null,
          "Entity": "03788f46-e430-4882-a097-e860d2c7aed5",
          "GUIHeaderIsOpened": "True",
          "Enabled": "True",
          "GUID": "d92b131a-a82f-487f-b1c1-25ff13496284"
        }
      ]
    }
  ]
}

推荐答案

Utf8JsonReader很难直接使用,因为它被设计用于从UTF 8字节跨度序列(通常是从管道生成的)中逐令牌地同步读取SON.

与直接与读者合作,将您的JSON deserialize变成您设计的与JSON对应的Data Transfer Object会容易得多. 将其反序列化后,您可以使用LINQ、AutoMapper或您喜欢的任何其他工具将其映射到最终模型.

使用https://json2csharp.com/(101中提到的工具之一),我生成了以下数据模型:

public class MapDTO
{
    // https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/immutability
    // Important: System.Text.Json requires that the constructor parameter names are the same as the corresponding property names, ignoring differences in case.
    [JsonConstructor]
    public MapDTO(string mapname) => this.Mapname = mapname;
    public MapDTO() : this("") { }
    
    [JsonPropertyName("Map name")]
    public string Mapname { get; }

    [JsonPropertyName("Entities")]
    public List<EntityDTO> Entities { get; set; }

    [JsonPropertyName("Entity components")]
    public List<EntityComponentDTO> Entitycomponents { get; set; }
}

public class ComponentDatumDTO
{
    [JsonPropertyName("Position")]
    public object Position { get; set; } // TODO: update with the correct type

    [JsonPropertyName("Rotation")]
    public object Rotation { get; set; } // TODO: update with the correct type

    [JsonPropertyName("Scale")]
    public object Scale { get; set; } // TODO: update with the correct type

    [JsonPropertyName("Entity")]
    public string Entity { get; set; }

    [JsonPropertyName("GUIHeaderIsOpened")]
    public string GUIHeaderIsOpened { get; set; }

    [JsonPropertyName("Enabled")]
    public string Enabled { get; set; }

    [JsonPropertyName("GUID")]
    public Guid GUID { get; set; } // Changed from string to Guid
}

public class EntityDTO
{
    [JsonPropertyName("Name")]
    public string Name { get; set; }

    [JsonPropertyName("Active")]
    public string Active { get; set; }

    [JsonPropertyName("GUID")]
    public Guid GUID { get; set; } // Changed from string to Guid
}

public class EntityComponentDTO
{
    [JsonPropertyName("Component type")]
    public string Componenttype { get; set; }

    [JsonPropertyName("Component data")]
    public List<ComponentDatumDTO> Componentdata { get; set; }
}

生成模型后,我进行了以下小更改:

  • 我引入了Mapname的参数化构造函数.

  • 我将GUID处房产的类型从string更改为Guid.

  • 我在每个类型名称后面添加了DTO

使用该模型,您的SON可以从字符串或文件反序列化为DTO,如下所示:

static JsonSerializerOptions DefaultOptions { get; } = new() { AllowTrailingCommas = true, ReadCommentHandling = JsonCommentHandling.Skip };

public MapDTO? ReadYamlFromFile(string filePath)
{
    using (var stream = File.OpenRead(filePath))
        return JsonSerializer.Deserialize<MapDTO>(stream, DefaultOptions);
}

public MapDTO? ReadYaml(string json) =>
    JsonSerializer.Deserialize<MapDTO>(json, DefaultOptions);

然后之后您可以将其映射到最终模型,而不必担心SON或大约Utf8JsonReader.

另请参阅:

演示小提琴here.

Csharp相关问答推荐

如何处理OpenTelegram中可以划分的大痕迹?

C#中的两个线程之间读写浮点类型

[0-n]范围内有多少个Integer在其小数表示中至少包含一个9?

List T.AddRange在传递ConcurrentDictionary作为参数时引发ArgumentExcellent

如何使嵌套for-loop更高效?

总是丢弃返回的任务和使方法puc无效之间有区别吗?

EF Core在请求列表时忽略列,但在按ID获取时包含

模型绑定RazorPage表单

需要在重新启动ApplicartionPool或IIS后启动/唤醒API的帮助

Blazor WebApp:原始异常:AADSTS700025:客户端是公共的,因此既不应显示客户端,也不应显示客户端

如何在C#中从正则表达式中匹配一些数字但排除一些常量(也是数字)

Rider将.NET安装在哪里

方法从数据表中只 Select 一个条件?

显示文档的ECDsa签名PDF在Adobe Reader中签名后已被更改或损坏

在IAsyncEnumerable上先调用,然后跳过(1)可以吗?

如何管理Azure认证客户端响应和证书 fingerprint

在C#ASP.NET内核中使用INT AS-1进行控制器场景的单元测试

解决方案:延长ABP框架和ANGING OpenIddict中的令牌生命周期

为什么当我try 为玩家角色设置动画时,没有从文件夹中拉出正确的图像?

try 创建一个C#程序,该程序使用自动实现的属性、覆盖ToString()并使用子类