Как сделать десериализацию JSON?

Есть такой такой класс:

public record ComplexUrl
{
    [JsonProperty("api")]
    public string ApiUrl { get; init; } = "";

    [JsonProperty("web")]
    public string? WebUrl { get; init; }
}

Нужно десериализировать в него json. Однако json может быть двух видов:

...
"links":
{    
    "self":
    {
        "api": "http://api.freelancehunt.com/v2/projects/299172",
        "web": "http://freelancehunt.com/project/project-with-bids/299172.html"
    },
    "bids": "...",
    "другие ссылки": "другие значения"
}
...

и

...
"links":
{   
    "self": "http://api.freelancehunt.com/v2/projects/299172",
    "другие ссылки": "другие значения"
}
...

Я пытался использовать кастомный конвертер и навесить его на свойство:

public abstract class FhDataResponse<T> : FhResponse
    where T : class
{
    // остальной код...

    [JsonProperty("links")]
    [JsonConverter(typeof(JsonComplexUrlConverter))]
    public IReadOnlyDictionary<string, ComplexUrl>? Urls { get; init; }
}

Но я не знаю как использовать дезериализацию по умолчанию:

internal class JsonComplexUrlConverter : JsonConverter<ComplexUrl>
{
    public override bool CanWrite => false;

    public override ComplexUrl? ReadJson(JsonReader reader, Type objectType, ComplexUrl? existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (objectType == typeof(string))
            return new() { ApiUrl = reader.Value!.ToString()! };
        else
            return // defalt converter;
    }

    public override void WriteJson(JsonWriter writer, ComplexUrl? value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Ответы (1 шт):

Автор решения: KuzCode

Решение:

  • Поменять аттрибут JsonProperty
  • Доделать конвертер

Класс ответа:

public abstract class FhDataResponse<T> : FhResponse
    where T : class
{
    // ...

    [JsonProperty("links", ItemConverterType = typeof(JsonComplexUrlConverter))] // <------
    public ReadOnlyDictionary<string, ComplexUrl>? Urls { get; init; }
}

Конвертер:

internal class JsonComplexUrlConverter : JsonConverter<ComplexUrl>
{
    public override bool CanWrite => false;

    public override ComplexUrl? ReadJson(JsonReader reader, Type objectType, ComplexUrl? existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.ValueType == typeof(string))
            return new ComplexUrl() { ApiUrl = reader.Value!.ToString()! };
        else
            return serializer.Deserialize<ComplexUrl>(reader)!;
    }

    public override void WriteJson(JsonWriter writer, ComplexUrl? value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
→ Ссылка