Nikita Goncharuk
Nikita Goncharuk

Reputation: 815

How can I Improve the efficiency of my Json parsing code?

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

Answers (2)

Lasse V. Karlsen
Lasse V. Karlsen

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

Liam
Liam

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

Related Questions