【问题标题】:Best way to upgrade JSON field to a class structure将 JSON 字段升级为类结构的最佳方法
【发布时间】:2021-01-26 10:22:21
【问题描述】:

只是想知道是否有人知道将 JSON 结构反序列化升级为新类类型的最佳方法。

进一步解释遗留值是

        public string author;

这已在 api 中更新为以下内容

 public class Author
{
    public string name;
    public string email;
    public string url;
}

public Author author;

所以现在我遇到了一个问题,即任何遗留数据都不能正确反序列化,因为它曾经是一个字符串,现在它是一个类。

我目前的解决方案是,如果它无法反序列化,则将其放入具有旧结构的类中,然后使用它进入新结构,但我觉得必须有更好的方法来转换旧的 sting 值作为流程的一部分进入新的类值。

谢谢

EDIT-1:

好的,我在下面的转换器方面取得了一些进展

public class AuthorConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Author user = (Author)value;
        writer.WriteValue(user);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        Author author = new Author();

        Debug.Log(objectType + "  " + reader.Value);
        if (reader.TokenType == JsonToken.String)
        {
            author.name = (string) reader.Value;
        }
        else if(reader.TokenType == JsonToken.StartObject)
        {
            try
            {
                JObject jObject = JObject.Load(reader);

                if (jObject.TryGetValue("name", out JToken name))
                {
                    author.name = name.Value<string>();
                }
                if (jObject.TryGetValue("email", out JToken email))
                {
                    author.email = email.Value<string>();
                }

                if (jObject.TryGetValue("url", out JToken url))
                {
                    author.url = url.Value<string>();
                }

            }
            catch (Exception e)
            {
                UnityEngine.Debug.Log(e);
                throw;
            }

        }
        return author;
    }

似乎一切都在工作,但感觉必须将值 1 乘 1 并转换过来有点繁琐,我尝试使用 jObject.ToObject 方法,但似乎导致了无限循环。无论哪种方式都有效,但我确信有更好的方法,所以仍然欢迎想法。

【问题讨论】:

    标签: json json.net


    【解决方案1】:

    由于您的Author 有一个默认(无参数)构造函数,您可以避免使用JsonSerializer.Populate(JsonReader, Object) 手动填充每个属性。并且为了避免编写自己的 WriteJson() 方法,覆盖 CanWrite 并返回 false。

    因此您的转换器可以重写如下:

    public class AuthorConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType) { return objectType == typeof(Author); }
    
        public override bool CanWrite { get { return false; } }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            try
            {
                if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
                    return null; // Or throw an exception if you don't want to allow null.
                else if (reader.TokenType == JsonToken.String)
                    return new Author { name = (string) reader.Value };
                else
                {
                    var author = new Author();
                    serializer.Populate(reader, author);
                    return author;
                }           
            }
            catch (Exception ex)
            {
                UnityEngine.Debug.Log(ex);
                throw;
            }
        }
    }
    
    public static partial class JsonExtensions
    {
        // Skip past any comments to the next content token, asserting that the file was not truncated.
        public static JsonReader MoveToContentAndAssert(this JsonReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException();
            if (reader.TokenType == JsonToken.None)       // Skip past beginning of stream.
                reader.ReadAndAssert();
            while (reader.TokenType == JsonToken.Comment) // Skip past comments.
                reader.ReadAndAssert();
            return reader;
        }
    
        // Read (advance to) the next token, asserting that the file was not truncated.
        public static JsonReader ReadAndAssert(this JsonReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException();
            if (!reader.Read())
                throw new JsonReaderException("Unexpected end of JSON stream.");
            return reader;
        }
    }
    

    注意事项:

    演示小提琴here.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-14
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      相关资源
      最近更新 更多