V
V
Vlad2021-10-27 14:11:59
ASP.NET
Vlad, 2021-10-27 14:11:59

Custom JsonConverter when the type to deserialize is determined by one of the keys?

Greetings!

I have a json with an interesting structure where the content is defined by the Type field .

public class Response : List<ResponseBase>
    {
    }

    public class ResponseBase
    {
        public string Type { get; set; }
    }

    // type = line
    public class ResponseLine : ResponseBase
    {
        public string Value { get; set; }
    }

    // type = bigline
    public class ResponseLineBig : ResponseBase
    {
        public string Title { get; set; }
    }

    // type = summary
    public class ResponseSummary : ResponseBase
    {
        public int ErrorCode { get; set; }
        public string ErrorMessage { get; set; }
        public string LogReference { get; set; }
        public string StatusMessage { get; set; }
        public string SuggestedSolution { get; set; }
    }


I have now made a JsonConverter, but reading and assigning properties is done by hand. If I don't want to do it manually (many different types in json), is there any way to make it easier?
//использую так
    //var response = await JsonSerializer.DeserializeAsync<Response>(responseStream, SerializerOptions);

    public class ReadOnlyJsonConverter : JsonConverter<ResponseBase>
    {
        public override bool CanConvert(Type typeToConvert)
        {
            return typeof(ResponseBase) == typeToConvert;
        }

        public override void Write(Utf8JsonWriter writer, ResponseBase value, JsonSerializerOptions options)
        {
            throw new NotImplementedException();
        }

        public override ResponseBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            using (JsonDocument document = JsonDocument.ParseValue(ref reader))
            {
                string dtoType = document.RootElement.Clone().GetProperty("Type").GetString();

                switch (dtoType)
                {
                    case "command":
                    case "line":
                        return ReadLine(document.RootElement.Clone());

                    case "summary":
                        return ReadSummary(document.RootElement.Clone());

                    default:
                        return null;
                }
            }
        }

        private ResponseLine ReadLine(JsonElement document)
        {
            var response = new ResponseLine()
            {
                Type = "line"
            };

            if (document.TryGetProperty("value", out JsonElement jsonElement))
            {
                response.Value = jsonElement.GetString();
            }

            return response;
        }

        private ResponseSummary ReadSummary(JsonElement document)
        {
            var response = new ResponseSummary()
            {
                Type = "summary"
            };

            if (document.TryGetProperty("errorMessage", out JsonElement jsonElementErrorMessage))
            {
                response.ErrorMessage = jsonElementErrorMessage.GetString();
            }

            if (document.TryGetProperty("statusMessage", out JsonElement jsonElementStatusMessage))
            {
                response.StatusMessage = jsonElementStatusMessage.GetString();
            }

            return response;
        }
    }

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
AndromedaStar, 2021-10-27
@AndromedaStar

No, it cannot be made easier, but reworking the code to make it more flexible and beautiful is a must.
I would make a factory of converters, and depending on the type, the necessary converter would be created.
In any case, for each new type, the strategy will have to be described, there is no getting away from this. It's just that the choice of strategy should definitely not be in the Read method.
There is also such a thing for polymorphic processing, I just remembered:
https://www.newtonsoft.com/json/help/html/Serializ...
Maybe this will help too, just the task is not completely formulated.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question