Reputation: 815
I wrote some code and it works, but I double-convert json twice, and it's a little embarrassing.
I get data that is wrapped in a "d" object, how can I get its contents right away
Here's the Json that I get:
{
"d": [
{
"__type": "MdoCommonWs.WsStructures.WsWmsLookupResult",
"CallResult": {
"Id": 0,
"Data": null,
"ErrorId": 0,
"ErrorDescription": null
},
"Article": {
"Id": "001",
"Description": "ANKER M12 MECHANISCH",
"Unit": "pieces",
"UnitPrice": 7,
"MinStock": 0,
"MaxStock": 0,
"Info": "ANKER MECHANISCH M12",
"Photo": [],
"PhotoUrl": "",
"WeightUnit": "kg",
"Weight": 0.05,
"CountStock": 0
},
"Locations": [
{
"LocationId": "00.00.AA.01.01.01.02",
"Type": 0,
"IsBlocked": false,
"ArticleId": "001",
"Stock": 2,
"TotalStock": 2,
"LastActionDate": "/Date(1480334382093)/",
"LastInventoryDate": "/Date(1480334319527)/"
}
],
}],
}
Here is my code to convert:
var rootJObject = JObject.Parse(stringSerialized);
var serialize = rootJObject["d"].ToString();
return JsonConvert.DeserializeObject<TResult>(serialize);
How can I do this more efficiently?
Upvotes: 2
Views: 702
Reputation: 391456
You could declare an object around your d
member:
public class Root<T>
{
[JsonProperty("d")]
public T Data { get; set; }
}
Then simply:
JsonConvert.DeserializeObject<Root<TResult>>(json).Data;
Another method is to deserialize into a JObject
:
public class Root
{
[JsonProperty("d")]
public JObject Data { get; set; }
}
JsonConvert.DeserializeObject<Root>(json).Data.ToObject<TResult>();
Upvotes: 2
Reputation: 29754
There are a number of ways to do this, here's what I use:
public async Task<IEnumerable<TResult>> ParseJson<TResult>(string stringSerialized)
{
using (StringReader streamReader = new StringReader(stringSerialized))
using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
{
JObject parsedData = await JObject.LoadAsync(jsonTextReader);
if (parsedData == null || parsedData["d"] == null || parsedData["d"].Children().Any() == false)
return new List<T>();
else
return parsedData["d"].Children().Select(s => s.ToObject<TResult>());
}
}
If stringSerialized
is coming from a Stream you can make this more efficient but just processing that stream directly, this saves you turning the stream into a string to turn the string into an object:
public async Task<IEnumerable<TResult>> ParseStream<TResult>(Stream contentStream)
{
using (StreamReader streamReader = new StreamReader(contentStream))
using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
{
jsonTextReader.DateFormatString = _dateFormatString;
JObject parsedData = await JObject.LoadAsync(jsonTextReader);
if (parsedData == null || parsedData["d"] == null || parsedData["d"].Children().Any() == false)
return new List<TResult>();
else
return parsedData["d"].Children().Select(s => s.ToObject<TResult>());
}
}
Be sure to dispose and clean up Stream contentStream
correctly using using
.
For a non async
version just replace:
JObject parsedData = await JObject.LoadAsync(jsonTextReader);
with
JObject parsedData = JObject.Load(jsonTextReader);
and change the signature to:
public IEnumerable<TResult> ParseJson<TResult>
Upvotes: 2