14

I am reading a NetworkStream for json string and then deserializing it using Newtonsoft.Json.

Sometimes, two json objects could be sent back-to-back and read at the same time on the stream. But the Newtonsoft.Json serializer gives me only one object.

For example, if I have the following string on the stream:

{"name":"John Doe","age":10}{"name":"Jane Doe","age":10}

If I deserialize the stream, the serializer reads the entire stream, but gives only the first object.

Is there a way to make the serializer read only the first object from the stream and then read the next object in the next iteration of a loop?

Code:

public static Person Deserialize(Stream stream)
{
    var Serializer = new JsonSerializer();
    var streamReader = new StreamReader(stream, new UTF8Encoding());
    return Serializer.Deserialize<Person>(new JsonTextReader(streamReader));
}

I cannot deserialize as a list because I'm not receiving a json array.

11
  • Can you include code you are using now for deserialization? Commented Feb 20, 2018 at 10:13
  • I found what seems to be a rather good Wikipedia page on the subject: en.wikipedia.org/wiki/JSON_streaming, quite general but still. Commented Feb 20, 2018 at 10:15
  • @Evk I've updated my question. Commented Feb 20, 2018 at 10:18
  • @PeterB Nice article, thanks! From the article, looks like the json I'm dealing with is concatenated json. Which is a good start. Now I need a way to do this in Json.net Commented Feb 20, 2018 at 10:19
  • There is a possible answer here: stackoverflow.com/questions/43747477/…. It works by skipping to the next { and parse an object from there, Commented Feb 20, 2018 at 10:19

2 Answers 2

15

I think you can do it like this:

public static IList<Person> Deserialize(Stream stream) {
    var serializer = new JsonSerializer();
    var streamReader = new StreamReader(stream, new UTF8Encoding());
    var result = new List<Person>();
    using (var reader = new JsonTextReader(streamReader)) {
        reader.CloseInput = false;
        // important part
        reader.SupportMultipleContent = true;
        while (reader.Read()) {
            result.Add(serializer.Deserialize<Person>(reader));
        }
    }
    return result;
}

Important part is SupportMultipleContent property, which notifies reader that there might be multiple json objects side to side.

Sign up to request clarification or add additional context in comments.

Comments

0

you can try it doing like this

        var httpRequest = HttpContext.Current.Request;
        // This list will have all the stream objects
        var persons = new List<Person>();
        if (httpRequest.Files.Count > 0)
        {
            for (var obj = 0; doc < httpRequest.Files.Count; obj++)
            {
                var postedFile = httpRequest.Files[obj];
                var bytes = new byte[postedFile.ContentLength];
                postedFile.InputStream.Read(bytes, 0, postedFile.ContentLength);
                persons.Add(Serializer.Deserialize<Person>(new JsonTextReader(new StreamReader(new MemoryStream(bytes)))));
            }
        }

1 Comment

Your solution will definitely work, but it's inefficient in many use cases. It requires the content to be completely retrieved, before the processing starts. It may also require high RAM upfront, if your entities are big.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.