C# 使用对象属性将 JSON 序列化和反序列化映射到引用对象

问题描述 投票:0回答:1

我有两个 JSON 文件:一个用于位置,另一个用于某个位置的对象。

locations.json =>

[
  {
    "Name": "Location#1",
    "X": 0,
    "Y": 20
  },
  {
    "Name": "Location#2",
    "X": 0,
    "Y": 19
  },
  ...
]

objects.json ==>

[
  {
    "Name": "Piano",
    "CurrentLocation": "Location#1"
  },
  {
    "Name": "Violin",
    "CurrentLocation": "Location#2"
  },
  ...
]

objects.json 使用位置名称引用位置实例。

我有两个类,可以反序列化到(或从中序列化):

public class ObjectOfInterest
{
    [JsonPropertyName("Name")]  
    public string Name { get; set; } = string.Empty;

    [JsonPropertyName("CurrentLocation")]
    public LocationNode CurrentLocation { get; set; } = new()
}

public class Location
{
    [JsonPropertyName("Name")]  
    public string Name { get; set; } = string.Empty;

    [JsonPropertyName("X")]
    public float X { get; set; }

    [JsonPropertyName("Y")]
    public float Y { get; set; }
}

如何创建采用字符串位置名称 JSON 属性的自定义 JSONSerializer 或转换器,并将正确的位置实例分配给 Objects 类?

c# json deserialization jsonserializer
1个回答
0
投票

将 JsonConverterAttribute 添加到 CurrentLocation 属性

public class ObjectOfInterest
{
    [JsonPropertyName("Name")]
    public string Name { get; set; } = string.Empty;

    [JsonPropertyName("CurrentLocation")]
    [JsonConverter(typeof(LocationConverter))]
    public Location CurrentLocation { get; set; } = new();
}

转换器应存储按其名称索引的位置:

public class LocationConverter : JsonConverter<Location>
{
    private readonly Dictionary<string, Location> _locationDictionary = new();

    public LocationConverter(IEnumerable<Location> locations)
    {
        foreach (var location in locations)
        {
            _locationDictionary[location.Name] = location;
        }
    }

    public override Location Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        string locationName = reader.GetString();
        if (_locationDictionary.TryGetValue(locationName, out Location location))
        {
            return location;
        }

        throw new KeyNotFoundException($"Location '{locationName}' not found.");
    }

    public override void Write(Utf8JsonWriter writer, Location value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.Name);
    }
}

最后,您可以像这样使用 LocationConverter:

var List<Location> locations = JsonSerializer.Deserialize<Location[]>(locationsJson);
var options = new JsonSerializerOptions
{
    Converters = new[]{ new LocationConverter(locations) }
};
var objects = JsonSerializer.Deserialize<ObjectOfInterest[]>(objectsJson, options);
© www.soinside.com 2019 - 2024. All rights reserved.