繁体   English   中英

c#-分两步对Json进行反序列化

[英]c# - Deserialize a Json in two steps

我想分两步对Json进行反序列化,因为我必须阅读第一部分才能知道它是哪种Object。

我必须阅读这种Json的文章:

{"header":3,"data":{"result":"myResult"}}

这样更易读

{
    "header":3,
    "data":{
        "result":"myResult"
    }
}

我在名为ProtocolHeader的类中反序列化此Json:

public class ProtocolHeader
{
    [JsonProperty("header")]
    public int Header { get; set; }

    [JsonProperty("data")]
    public string Data { get; set; }
}

为此,我使用以下代码:

JsonConvert.DeserializeObject<ProtocolHeader>(Json)

根据Header的值,我将选择不同的类来反序列化文件的末尾。

例如我可以再上一个课

public class ProtocolResult
{
    [JsonProperty("result")]
    public string Result{ get; set; }
}

或那样

public class ProtocolError
{
    [JsonProperty("errorNumber")]
    public int ErrorNumber{ get; set; }

    [JsonProperty("additionalInformation")]
    public string AdditionalInformation{ get; set; }
}

您有两个步骤来分离反序列化对象的想法吗?

谢谢

你可以上3节课。 一个具有所有字段的通用类(不是基类),然后是ProtocolResult和ProtocolError

然后对每个对象执行隐式转换。 您还可以将IsError getter放入普通类中,以决定如何使用它。

您可以使用阅读器仅在需要时阅读,然后跳出阅读器进行真正的反序列化。

可能比先反序列化为简单对象然后反序列化为实际对象要好得多,但这是另一种选择。

您可能可以对此稍作调整。

string json = @"{""header"":3,""data"":{""result"":""myResult""}}";

using (var stringReader = new StringReader(json))
{
    using (var jsonReader = new JsonTextReader(stringReader))
    {
        while (jsonReader.Read())
        {
            if (jsonReader.TokenType == JsonToken.PropertyName 
                && jsonReader.Value != null
                && jsonReader.Value.ToString() == "header")
            {
                jsonReader.Read();
                int header = Convert.ToInt32(jsonReader.Value);
                switch (header)
                {
                    case 1:
                        // Deserialize as type 1
                        break;
                    case 2:
                        // Deserialize as type 2
                        break;
                    case 3:
                        // Deserialize as type 3
                        break;
                }
                break;
            }
        }
    }
}

选项1:在data类中不使用抽象基类。

我发现最简单的方法如下:

  1. 使用JToken作为未知对象的字段类型声明您的类。

     [JsonObject(MemberSerialization.OptIn)] public class ProtocolHeader { [JsonProperty("header")] private int _header; [JsonProperty("data")] private JToken _data; } 
  2. 公开属性中的专用数据。

     public ProtocolResult Result { get { if (_data == null || _header != ResultHeaderValue) return null; return _data.ToObject<ProtocolResult>(); } } public ProtocolError Error { get { if (_data == null || _header != ErrorHeaderValue) return null; return _data.ToObject<ProtocolError>(); } } 

选项2:对data类使用抽象基类。

另一种选择是为各种数据类型创建抽象基类,并在抽象基类中创建静态方法以执行类型选择和适当的反序列化。 当类型信息包含在对象本身中时(例如,如果headerdata对象内部的属性),这特别有用。

  1. LoadBalancerConfiguration<T>._healthMonitor字段的类型为JObject ,但是同一类中的HealthMonitor属性返回一个HealthMonitor对象。
  2. HealthMonitor.FromJObject方法执行实际的反序列化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM