-1

need to deserialize this JSON using newtonsoft.json.net:

{
  "dataset": {
    "id": 36592406,
    "dataset_code": "EON_X",
    "database_code": "FSE",
    "start_date": "2019-11-18",
    "end_date": "2019-11-18",
    "data": [
      [
        "2019-11-18",
        9.17,
        9.204,
        9.121,
        9.167,
        null,
        6088172.0,
        55793844.0,
        null,
        null,
        null
      ]
    ]

  }
}

to List<FseItem>. Problem is that i need only "data" part. I was trying to use this:

            var settings = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                MissingMemberHandling = MissingMemberHandling.Ignore
            };

            var json = GetResult(url);
            var obj = JsonConvert.DeserializeObject<List<FseItem>>(json, settings);

here is my FseItem object:

        public class FseItem
        {
            public DateTime Date { get; set; }
            public decimal Open { get; set; }
            public decimal High { get; set; }
            public decimal Low { get; set; }
            public decimal Close { get; set; }
            public decimal Change { get; set; }
            public decimal TradedVolume { get; set; }
            public decimal TurnOver { get; set; }
            public decimal LastPrice { get; set; }
            public decimal TradedUnits { get; set; }
            public decimal DailyTurnover { get; set; }
        }

but i get this error: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[InvestorWeb2.WebUI.Domain.QwertyReporting.FseReport+FseItem]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

I get my JSON from Quandl free databases, so i can't change anything in json data. In this example json contain only one element, but i will work with big json files as well. What are problems in my code, and what should i do to fix them?

Fast solution for a lot of data and some advice about parsing and working with big json's will be appreciated!

  • Is this even valid json? JSONLint is saying its not... – maccettura Nov 19 '19 at 16:58
  • All the different json specifications are failing, it's not valid `json`. Since you are getting the data from another place, I would let them know it's wrong and needs fixed. If you remove `,` from `],` at the bottom, it will pass `rfc 8259` specs. – Trevor Nov 19 '19 at 16:59
  • 1
    Only part of the JSON text represents an array but your code is treating the entire thing as a collection/array. [Start your research here](https://stackoverflow.com/q/21358493/1070452) – Ňɏssa Pøngjǣrdenlarp Nov 19 '19 at 17:09
  • 1
    please check your json as it is not valid, i think you forgot to delete a comma . – sayah imad Nov 19 '19 at 17:48
  • My fault, i removed some data to make my example simpler. I edited json, so it is valid atm. But still have error while trying to get list of object when deserializing – Alexander Groshev Nov 20 '19 at 06:57

1 Answers1

1

Okey, i've researched couple of different info and that's what i've found:

First of all what i need is to use RootObject for my whole JSON, so i've added some more objects:

 public class RootObject
        {
            [JsonProperty("dataset_data")]
            public Dataset dataset_data { get; set; }
        }

        public class Dataset
        {
            [JsonProperty("frequency")]
            public string frequency { get; set; }

            [JsonProperty("start_date")]
            public DateTime start_date { get; set; }

            [JsonProperty("end_date")]
            public DateTime end_date { get; set; }

            [JsonProperty("data")]
            public List<FseItem> data { get; set; }
        }

the problem is that my JSON Array doesn't have name for his elements. Looks like the only way to deserialize array to object is by using converter:

[JsonConverter(typeof(FseItemConverter))]
        public class FseItem
        {
            public DateTime Date { get; set; }
            public decimal? Open { get; set; }
            public decimal? High { get; set; }
            public decimal? Low { get; set; }
            public decimal? Close { get; set; }
            public decimal? Change { get; set; }
            public decimal? TradedVolume { get; set; }
            public decimal? TurnOver { get; set; }
            public decimal? LastPrice { get; set; }
            public decimal? TradedUnits { get; set; }
            public decimal? DailyTurnover { get; set; }
        }


 public class FseItemConverter : JsonConverter
    {

        public override bool CanConvert(Type objectType)
        {
            return objectType.Name.Equals("FseItem");
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {

            JArray array = JArray.Load(reader);
            return new FseReport.FseItem
            {
                Date = array[0].ToObject<DateTime>(),
                Open = array[1].ToObject<decimal?>(),
                High = array[2].ToObject<decimal?>(),
                Low = array[3].ToObject<decimal?>(),
                Close = array[4].ToObject<decimal?>(),
                Change = array[5].ToObject<decimal?>(),

                TradedVolume = array[6].ToObject<decimal?>(),
                TurnOver = array[7].ToObject<decimal?>(),
                LastPrice = array[8].ToObject<decimal?>(),
                TradedUnits = array[9].ToObject<decimal?>(),
                DailyTurnover = array[10].ToObject<decimal?>()

            };
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var orderItem = value as FseReport.FseItem;
            JArray arra = new JArray();
            arra.Add(orderItem.Date);
            arra.Add(orderItem.Open);
            arra.Add(orderItem.High);
            arra.Add(orderItem.Low);
            arra.Add(orderItem.Close);
            arra.Add(orderItem.Change);
            arra.Add(orderItem.TradedVolume);
            arra.Add(orderItem.TurnOver);
            arra.Add(orderItem.LastPrice);
            arra.Add(orderItem.TradedUnits);
            arra.Add(orderItem.DailyTurnover);

            arra.WriteTo(writer);
        }
    }

And also, talking about big JSON data, it's much better to use Stream and JsonReader, not string to read json data from URL:

HttpClient client = new HttpClient();

            using (Stream s = client.GetStreamAsync(url).Result)
            using (StreamReader sr = new StreamReader(s))
            using (JsonReader reader = new JsonTextReader(sr))
            {
                JsonSerializer serializer = new JsonSerializer();

                var result = serializer.Deserialize<RootObject>(reader);

                return result.dataset_data.data;
            }

Hope this info will be helpfull for some one. Maybe there is some ways to improve this, but it works for me, so i'll post it here

  • 1
    And also good tip for RootObject is to use "Paste Special" in visual studio (Edit -> Paste Speacial -> Paste JSON to classes). It will make C# class from JSON code using code generation. Very comfortable option for deserializing – Alexander Groshev Nov 20 '19 at 07:55
  • Also, another way how to make this without converter you can find in this question: [link](https://stackoverflow.com/questions/58997236/newtonsoft-json-converter-for-json-with-filters/59004322#59004322) – Alexander Groshev Nov 25 '19 at 07:10