0

I am trying to deserialize my json data from a file shown below. But my jsontextreader only reads one object on the file. Why is not reading until the end of the file? I get no errors on this when I build and inputs one line of json data to my windows form datagridview.

var quotes = new List<Desk.DeskObject>();

       var serializer = new JsonSerializer();
       using (var reader = new StreamReader(@"quotes.json"))
       using (var jsonReader = new JsonTextReader(reader))
       {
            quotes = serializer.Deserialize<List<Desk.DeskObject>>(jsonReader);
       }

Below is Json data

[
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Jonathan Smith",
    "Width": 43,
    "Depth": 43,
    "numOfDrawers": 1,
    "surfMaterial": "Oak",
    "RushOrderDays": 3,
    "TotalQuote": 1339
  }
][
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Tim Taylor",
    "Width": 24,
    "Depth": 44,
    "numOfDrawers": 3,
    "surfMaterial": "Laminate",
    "RushOrderDays": 5,
    "TotalQuote": 556
  }
][
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Cindy Crawford",
    "Width": 24,
    "Depth": 24,
    "numOfDrawers": 5,
    "surfMaterial": "Pine",
    "RushOrderDays": 5,
    "TotalQuote": 570
  }
]
Himanshu
  • 12,071
  • 7
  • 46
  • 61
bashamjr
  • 3
  • 1
  • 1
    Your JSON file is 3 lists after eachother, not a list with 3 items in it. – fredrik Feb 10 '18 at 15:36
  • So you think it has to do with how I am serializing my data to begin with to file??? List deskObjects = new List(); deskObjects.Add(deskObject); var serializer = new JsonSerializer(); using (StreamWriter file = File.AppendText(@"quotes.json")) { serializer.Serialize(file, deskObjects); } – bashamjr Feb 10 '18 at 15:39
  • If you create the file yourself, yes. Either change how you serialize so you get one list in the file, or read until end of file and deserialize multiple lists - adding the read list to a total list. – fredrik Feb 10 '18 at 15:40
  • Don't post blocks of code in comments, it's hard to read. But it looks like you're only serializing one object at a time. Add them all to one list and then serialize. – fredrik Feb 10 '18 at 15:41
  • You can validate your JSON online, e.g. here https://jsonlint.com/ [yours fails] – Stephen Kennedy Feb 10 '18 at 15:45
  • Looks almost but not quite like [newline delimited JSON](http://ndjson.org/) - only with line breaks wrongly placed. Nevertheless the following should work for your file also: [Parsing large json file in .NET](https://stackoverflow.com/q/32227436) and [Line delimited json serializing and de-serializing](https://stackoverflow.com/q/29729063). – dbc Feb 10 '18 at 23:12
  • And, if you want to write correctly formatted newline delimited JSON, see [Serialize as NDJSON using Json.NET](https://stackoverflow.com/q/44787652). It's a useful format to use when you need to periodically append items to a large file and want to avoid loading the entire file every time. – dbc Feb 10 '18 at 23:14

2 Answers2

1

You are not serializing a list of 3 DeskObjects - Your JSON suggests that you are serializing a list of 1 DeskObject three times.

I used something close to your code in this code. Without seeing your full serialization/object creation code, I can't tell what's going on exactly. But it looks like you are serializing one DeskObject in your comment above and not a list of 3 DeskObjects.

In my example, I instantiate 3 DeskObjects inline in a list like so:

List<DeskObject> list = new List<DeskObject>() { new DeskObject(){...}, new DeskObject(){...}, new DeskObject(){...} } ;

You could also create your DeskObjects and get them into the list provided they were already created previously:

list.Add(myDeskObject1);
list.Add(myDeskObject2);
list.Add(myDeskObject3);

Then, after the list is completely full:

var serializer = new JsonSerializer();
using (StreamWriter file = new StreamWriter(@"quotes.json", false))
                         { serializer.Serialize(file, list); }

This results in the following JSON:

[
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Jonathan Smith",
    "Width": 43,
    "Depth": 43,
    "numOfDrawers": 1,
    "surfMaterial": "Oak",
    "RushOrderDays": 3,
    "TotalQuote": 1339
  },
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Tim Taylor",
    "Width": 24,
    "Depth": 44,
    "numOfDrawers": 3,
    "surfMaterial": "Laminate",
    "RushOrderDays": 5,
    "TotalQuote": 556
  },
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Cindy Crawford",
    "Width": 24,
    "Depth": 24,
    "numOfDrawers": 5,
    "surfMaterial": "Pine",
    "RushOrderDays": 5,
    "TotalQuote": 570
  }
]

Which correctly parses into a list of 3 DeskObjects. The only way I could manage to get JSON like yours into the file was to use this code.

tl;dr make sure you fill your list before serializing it.

Edit:

Reviewing your code, this is your issue.

 var deskObjects = new List<Desk.DeskObject>();
                deskObjects.Add(deskObject);
                var result = JsonConvert.SerializeObject(deskObject, Formatting.Indented);
File.AppendAllText(@"quotes.json", result);

You are creating a new List every time you have a new quote, and serializing it, then appending that to file. This means you are appending '[{item}]' to a file that contains [{item1}][{item2}], etc.

Instead you need to read the List of DeskObjects out of the JSON first, so that you actually have a C# collection. Then add the current DeskObject to it. Finally, rewrite the entire file again (do not append) by serializing the new list.

I am trying to direct you there without writing the code for you - it's important that you understand the concept that when you call AppendAllText, you are not inserting something into a JSON tree. You are just appending raw text to the end of a file containing raw text.

  • How can I add to the List each time a quote is entered would I just leave open curly braces? When I add to my list it just overrides the first one entered. – bashamjr Feb 10 '18 at 16:34
  • Without seeing code for how you are adding to the list (complete code) it's hard to say. Are you creating the list again with new List() every time a quote comes in? In that case, you're emptying out the list every time you do that. Call 'new List' ONCE, Add items to the list (1 or more), then Write your JSON. – Justin Capalbo Feb 10 '18 at 16:44
  • you can see what I am doing here on these two forms [AddQuote.cs](https://github.com/bashamjr/MegaDesk_4_JonathanBasham/blob/master/MegaDesk-4-JonathanBasham/AddQuote.cs) and [ViewAllQuotes.cs](https://github.com/bashamjr/MegaDesk_4_JonathanBasham/blob/master/MegaDesk-4-JonathanBasham/ViewAllQuotes.cs) this would work if the data was in correct json format [{},{}] – bashamjr Feb 10 '18 at 19:22
  • Your StreamWriter has no awareness of what is in your file. It cannot detect the fact that you are trying to insert JSON into an existing JSON tree. You are effectively just appending an entire new JSON object to the end of the file every time. Instead of creating a new list and appending it to the file, read the file (if it exists) into a List, add your new item to that list, serialize the result, then rebuild the file. If it's the first quote in the file, you'll have to initialize the List yourself with 'new'. This way, the JSON in the file will "grow" correctly. – Justin Capalbo Feb 10 '18 at 19:43
  • Great. The problem is that once the JSON is in the text file, as far as your streamwriter/JSON object are concerned, it's just text in there. So you need to re-generate the JSON after you have a list with more stuff in it, then re-write it. I'd strongly advise keeping this code isolated from the rest of your application so you don't end up with duplicated "Read list from JSON" code everywhere. – Justin Capalbo Feb 10 '18 at 20:26
0

Your JSON is malformed, so it's surprising it's getting parsed at all. Here is what you, probably, want:

[
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Jonathan Smith",
    "Width": 43,
    "Depth": 43,
    "numOfDrawers": 1,
    "surfMaterial": "Oak",
    "RushOrderDays": 3,
    "TotalQuote": 1339
  },
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Tim Taylor",
    "Width": 24,
    "Depth": 44,
    "numOfDrawers": 3,
    "surfMaterial": "Laminate",
    "RushOrderDays": 5,
    "TotalQuote": 556
  },
  {
    "CurrentDate": "09 Feb 2018",
    "CustomerName": "Cindy Crawford",
    "Width": 24,
    "Depth": 24,
    "numOfDrawers": 5,
    "surfMaterial": "Pine",
    "RushOrderDays": 5,
    "TotalQuote": 570
  }
]
Tyrrrz
  • 2,492
  • 1
  • 19
  • 29