1

I need to deserialize this weird JSON (image below). I've seen some deserialization hints using Dictionary<>, etc. but the problem is that "parameters" contains different data, then previous keys.

Can I somehow get it to work using JsonSerializer deserializator without doing foreach loops and other suspicious implementations? I do need data from "data" in my application.

Here's some of my code:

using var client = new WebClient();
var json = client.DownloadString(GetJsonString());
var invoicesData = JsonSerializer.Deserialize<JsonMyData>(json, options);

If using Newtonsoft is necessary I might start using it.

Text

Michał Droździk
  • 324
  • 1
  • 3
  • 10
  • 1
    Does this answer your question? [Deserialize JSON to anonymous object](https://stackoverflow.com/questions/6904825/deserialize-json-to-anonymous-object) – Jawad Jan 04 '20 at 20:42
  • Just to confirm, you're using [tag:system.text.json] not [tag:json.net], correct? Also, can you please [edit] your question to include your JSON as **text** rather than as a bitmap? It's policy here not to to use images for textual data, see [*Discourage screenshots of code and/or errors*](https://meta.stackoverflow.com/a/307500) and [*Why not upload images of code on SO when asking a question*](https://meta.stackoverflow.com/a/285557) for why. A [mcve] showing the code that does not work would increase your chances of getting an answer, for why see [ask]. – dbc Jan 04 '20 at 22:22
  • Does the value of `"parameters"` have a different schema than the value for the indexed values `"0"`, `"1"` etc etc? Do the indexed values have a shared, fixed schema, or is everything free-form? – dbc Jan 04 '20 at 22:26
  • Does this correspond to the situation described in [How to deserialize a child object with dynamic (numeric) key names?](https://stackoverflow.com/q/40088941/3744182)? – dbc Jan 04 '20 at 22:35

3 Answers3

2

With Newtonsoft you can parse and access arbitrary JSON documents, even ones that can't reasonably be deserialized into a .NET object. So something like:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;

namespace ConsoleApp35
{
    class Program
    {
        static void Main(string[] args)
        {
            var json = @"
{
                ""myData"" : 
    {
      ""0"" : { ""data"": { ""A"":1,""B"":2} },
      ""1"" : { ""data"": { ""A"":1,""B"":2} },
      ""2"" : { ""data"": { ""A"":1,""B"":2} },
      ""3"" : { ""data"": { ""A"":1,""B"":2} },
      ""parameters"" : { ""p"":""a""}
    },
 ""status"":{ }
}";

            var foo = JObject.Parse(json);
            var a = foo["myData"]["1"]["data"];
            Console.WriteLine(a);

            Console.WriteLine("Hit any key to continue");
            Console.ReadKey();
        }
    }
}
David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67
  • I'll try it later and see what I've ended up with, thanks EDIT: I meant I need a collection of all "data" entries. So basically I have to foreach with everything? Full json is like +1000 entries of data – Michał Droździk Jan 04 '20 at 22:04
  • Since you're transforming a JSON object into a collection, yes, you'll have to iterate them and add them to a collection. – David Browne - Microsoft Jan 04 '20 at 22:17
  • Thanks a lot, at the end I figured out I could just remove "parameters" via JToken.Last.Remove() and then deserialized everything in foreach loop. Your reply was very helpful :) – Michał Droździk Jan 07 '20 at 14:20
1

I think you should really consider using Newtonsoft.Json instead of default JsonDeserializer, it is much easier to use in such situations.

Fedir Katushonok
  • 391
  • 5
  • 13
0

If you are interested in processing this without foreach loops and wanting to access the data in a list format, I would suggest using Dictionary for this. When you use dictionary, you can use Objects as values that would compensate for differences in numbers (0, 1, 2, ..) and words (parameters).

    // Classes to Deserialize data we need.
    public class MyObject
    {
        [JsonProperty("data")]
        public Data Data { get; set; }
    }

    public class Data
    {
        public int A { get; set; }
        public int B { get; set; }
    }

Usage in Main

    // Read in the JSON
    var myData = JsonConvert.DeserializeObject<dynamic>(jsonString)["myData"];

    // Convert To Dictionary
    Dictionary<string, dynamic> dataAsObjects = myData.ToObject<Dictionary<string, dynamic>>();

    string searchFor = "3";
    dataAsObjects.TryGetValue(searchFor, out dynamic obj);
    if (obj != null)
    {
        // Conversion to int and matching against searchFor is to ensure its a number.
        int.TryParse(searchFor, out int result);
        if (result == 0 && result.ToString().Equals(searchFor))
        {
            MyObject myObject = obj.ToObject<MyObject>();
            Console.WriteLine($"A:{myObject.Data.A} - B:{myObject.Data.B}");
        }
        else if (result == 8 && result.ToString().Equals(searchFor))
        {
            // I am not clear on whats your parameters class look like.
            MyParameters myParams = obj.ToObject<MyParameters>();
        }
    }

Output

A:1 - B:2

With this method you can either access the numbers or the parameters element.

Jawad
  • 11,028
  • 3
  • 24
  • 37