6

Greatings! I need to deserialize a file of different objects serialized as json. Here is the resulting file:

{
  "Number": 1,
  "Description": "Run version with strategy data",
  "Context": "NA"
}[
  {
    "N": 0.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.0,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 1.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.2999999523162842,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 2.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.0,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 3.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.2999999523162842,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 4.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.0,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 5.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.2999999523162842,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 6.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.0,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 7.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.2999999523162842,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 8.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.0,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  },
  {
    "N": 9.0,
    "T": 2.0,
    "Adc": [
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0,
      0.0
    ],
    "SpltFr": 2.2999999523162842,
    "Acc": 1.0,
    "DAcc": 0.0,
    "Acc2": 1.0,
    "OscFr": 0.5,
    "Fltr": 0,
    "CmpEr": false,
    "ErrPck": 0,
    "IndxDiff": 0,
    "Pos": 0,
    "FastAcc": [],
    "GIndx": 0,
    "Indx": 0,
    "PcTime": "0001-01-01T00:00:00"
  }
]

I'm using json.net but that seem that it's doesn't work as I want it to.

StreamReader reader = new StreamReader(fileName, Encoding.GetEncoding(1251));
var serializer = new JsonSerializer() { CheckAdditionalContent = false };
var obj1 = serializer.Deserialize(reader, typeof(Type1));
var obj2 = serializer.Deserialize(reader, typeof(Type2));

This code reads only the first object and throws exeption while reading the second. What do I do wrong? Can the json.net even fulfill my task? Thanks in advance!

Taking some advices from this topic in account I've modified my code into this:

using (FileStream fs = File.Open(fileName, FileMode.Open))
using (StreamReader sr = new StreamReader(fs, Encoding.GetEncoding(1251)))
using (JsonTextReader jr = new JsonTextReader(sr))
{

     JsonSerializer serializer = new JsonSerializer()
     {
            Formatting = Newtonsoft.Json.Formatting.Indented,
            CheckAdditionalContent = false,
            TypeNameHandling = TypeNameHandling.Auto

     };
     var data1 = serializer.Deserialize(jr, typeof(Type1));

     var data2 = serializer.Deserialize(jr, typeof(List<Type2>));
}

But it still doesn't work properly. Seems that after reading the first object my cursor doesn't stop immediately at the end of it but somewhere in the second object. Therefore my reader can't read any objects any more.

PanCotzky
  • 564
  • 2
  • 5
  • 12
  • 1
    It works as expected. `{}{}` is not a valid json. See the definition of [XY-problem](http://www.perlmonks.org/?node_id=542341) – I4V Sep 14 '13 at 19:44
  • The reason why I do it this way is that sometimes I don't need to read all the objects. Sometimes I will need only first and second. If I just put my objects into a single json I will have to parse all the objects. I need to parse each of the objects separately to be able to decide which of them shouldn't be parsed. – PanCotzky Sep 14 '13 at 22:42
  • What exception are you getting? – svick Sep 14 '13 at 22:58
  • @PanCotzky But I assume, you have already noticed that this is not the way you go. You should device a way to read the json objects one by one and then give them to Json.net – I4V Sep 14 '13 at 23:00
  • @svick Is the exception important? storing multiple jsons(and also xmls) in a single file is a problem. – I4V Sep 14 '13 at 23:04
  • @I4V I don't see why should it be a problem. `{}{}` is not valid JSON, but `{}` and `{}` are. So you can treat the file not as a single string, but as a stream: first read the first JSON and then the second. – svick Sep 14 '13 at 23:10
  • @svick to be able to read them one by one, there must be a separator. a newline char (for ex), or some headers showing the positions of json objects. So exception you are asking is still not important. – I4V Sep 14 '13 at 23:18
  • 2
    @I4V Why? You're at position 0, you read the whole first JSON object and stop when you have read the whole object. Now you're at the position where the second object starts, so you can repeat the process. There is no need for separators. – svick Sep 14 '13 at 23:20
  • 1
    @svick If you were the writer of Json serializers, it would work. But this is not the case (or you have already developed a json serializer that I don't know). (I am talking of wellknown json serilaizers)See how twitters streaming API work. It sends jsons objects *line by line*, assuring there is no newline char in the json. – I4V Sep 14 '13 at 23:22
  • @svick unless you develop your own json serializer, you will have to obey the rules of existing ones. – I4V Sep 14 '13 at 23:31
  • @I4V You're right, but this is a problem with JSON.NET (and possibly other parsers), not something inherent in JSON, which it sounded like you were claiming. – svick Sep 14 '13 at 23:36
  • @svick, So what is your point other than saying, *In theory, it could have been implemented*. In which way should your comments help to OP. – I4V Sep 14 '13 at 23:41
  • @svick I think the idea is simple: json parsers parse a single json object, if you want them to parse many objects, you should find a way to feed them one by one – I4V Sep 14 '13 at 23:48
  • Well I tried to do exactly what you said (reading json objects as a stream one by one) but after reading the first object it resets the cursor back to start of the file. Infact this is the reason why I asked this question. May be I'm loosing something crucial in a concept of StreamReader? – PanCotzky Sep 15 '13 at 10:05
  • 1
    The updated code works for me, assuming you use the version of JSON.NET with my change. – svick Sep 16 '13 at 22:43

2 Answers2

5

UPDATE: The latest master of JSON.NET now supports this by setting SupportMultipleContent on JsonReader.


As far as I know, JSON.NET doesn't support this, so I decided to implement this feature. The result is on github, usage would be like this:

var reader = new JsonTextReader(
    new StreamReader(fileName, Encoding.GetEncoding(1251)));
var serializer = new JsonSerializer { CheckAdditionalContent = false };
var obj1 = serializer.Deserialize(reader, typeof(Type1));
var obj2 = serializer.Deserialize(reader, typeof(Type2));

You need to explicitly use JsonTextReader here, because that's what holds characters read from the TextReader.

svick
  • 236,525
  • 50
  • 385
  • 514
  • That helped partially. Now I'm expiriencing other kind of problem. For some reasone when my serializer starts to read the second object it drops out with the exeption "Unexpected token while deserializing object: EndObject. Path '', line 5, position 2.". I've added a file contents to my question. – PanCotzky Sep 15 '13 at 17:34
  • @PanCotzky It works for me. Though with the second value, the type has to be a collection, for example `Type2[]`. – svick Sep 15 '13 at 18:17
  • I've found out that the next object does not deserialize because the cursor stops not on the end of the first object but few lines further. Seems like the parser reads the file not line by line but rather by fetching an entire bunch of lines. Have you met this kind of problem before? – PanCotzky Sep 16 '13 at 19:58
  • @PanCotzky Did you use the code as I wrote it? Like I said, using `JsonTextReader` is important there, without that, you would see something like you describe. – svick Sep 16 '13 at 20:02
  • Yes, I did exactly that what you've wrote. Did you actually tried that for yourself and that worked? May be I've configured my reader incorrectly? I'll write my new code in the question. – PanCotzky Sep 16 '13 at 22:04
  • I've encountered some problems with your build of Json.net. May be you could help me? At some point it can't be loaded correctly (throws the exception:"Could not load file or assembly "Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=null" or one of its dependencies"). Did you encountered this error before? – PanCotzky Oct 03 '13 at 07:48
  • @PanCotzky You should probably ask a new question about that. – svick Oct 03 '13 at 10:07
  • I've encountered the @PanCotzky's issue too ("Unexpected token: End object"). The simple `if ( reader.TokenType == JsonToken.EndObject ) reader.Read(); ` in my reading loop took care of this. – HellBrick Jul 21 '14 at 08:59
3

This question was asked again, and a good working sample is here: https://stackoverflow.com/a/26610684/3591916

Here is my test code based on the above link:

var reader = new JsonTextReader(Console.In);
reader.SupportMultipleContent = true;
var serializer = new JsonSerializer();

while (reader.Read())
{
    try
    {
        var message = serializer.Deserialize<string>(reader);
        Console.WriteLine("Got message: {0}", message);
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);
    }
}

Hope this helps someone.

Community
  • 1
  • 1
Paul
  • 1,011
  • 10
  • 13