I would like to deserialize my Json in two step because I have to read the first part to know what kind of Object it is.
I have to read this kind of Json :
{"header":3,"data":{"result":"myResult"}}
it's more readable like that
{
"header":3,
"data":{
"result":"myResult"
}
}
I deserialize this Json in a class named ProtocolHeader :
public class ProtocolHeader
{
[JsonProperty("header")]
public int Header { get; set; }
[JsonProperty("data")]
public string Data { get; set; }
}
To do this I use this code :
JsonConvert.DeserializeObject<ProtocolHeader>(Json)
Depending on the value of the Header, I will choose different class to deserialize the end of the file.
For example, I could have another class
public class ProtocolResult
{
[JsonProperty("result")]
public string Result{ get; set; }
}
or like that
public class ProtocolError
{
[JsonProperty("errorNumber")]
public int ErrorNumber{ get; set; }
[JsonProperty("additionalInformation")]
public string AdditionalInformation{ get; set; }
}
Do you have an idea to seperate the Deserialize Object in two steps ?
Thanks
You could make 3 classes. One common class (not base) which has all of the fields, then a ProtocolResult & ProtocolError
Then implement an implicit cast to each. You could also put a IsError getter on to your common class to decide how to use it.
You can use a reader to only read as long as you need, then skip out of the reader and do your real deserialization.
Probably not a whole lot better than deserializing into a simple object first then a real object later, but it's an alternative.
You can probably tweak this a bit.
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;
}
}
}
}
data
classes. The easiest I've found to do this is as follows:
Declare your class using JToken
as the field type for the unknown object.
[JsonObject(MemberSerialization.OptIn)] public class ProtocolHeader { [JsonProperty("header")] private int _header; [JsonProperty("data")] private JToken _data; }
Expose the specialized data in properties.
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>(); } }
data
classes. Another option is to create an abstract base class for the various data types, and create a static method in the abstract base class to perform the type selection and proper deserialization. This is particularly useful when the type information is contained in the object itself (eg if header
was a property inside the data
object).
LoadBalancerConfiguration<T>._healthMonitor
field has the type JObject
, but the HealthMonitor
property in the same class returns a HealthMonitor
object. HealthMonitor.FromJObject
method performs the actual deserialization.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.