Microsoft Developer
Microsoft Developer

Reputation: 5459

Read text file with multiple JSON messages

I have a text file which contains multiple JSON messages. There is no separator except new line. I have a method which will take JSON string and deserialize it to some object type.

How can I read text file and iterate through each Json string so that it can be deserialized?

Below is the method for deserialize:

public static T JsonDeserialize<T>(string jsonString)
{
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
    MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
    T obj = (T)ser.ReadObject(ms);
    return obj;
}

Upvotes: 4

Views: 8441

Answers (5)

M.Hassan
M.Hassan

Reputation: 11032

You can use jsonReader.SupportMultipleContent Property.
It doesn't matter the separation between the messages newline(s), tab or space(s).

SupportMultipleContent sets a value true/false (default is false) indicating whether multiple pieces of JSON content can be read from a continuous stream without error.

Example:

public static void Main()
{   
    string json = @"
    {
        'Name': 'foo',
        'Id': 123
    }{
        'Name': 'bar',
        'Id': 456
    }
    
    //more new line
    {
        'Name': 'jar',
        'Id': 789
    }
    ";

     var persons = DeserializeObjects<Person>(json).ToList();
     Console.WriteLine(persons.Count());
     foreach ( var person in persons)
    {
      Console.WriteLine("id: {0}, Name: {1}",person.Id, person.Name);
    }

}

    static IEnumerable<T> DeserializeObjects<T>(string input)
    {
        JsonSerializer serializer = new JsonSerializer();
        using (var strreader = new StringReader(input)) 
        using (var jsonreader = new JsonTextReader(strreader))
        {
                //you should use this line
                jsonreader.SupportMultipleContent = true;
                while (jsonreader.Read()) 
                {                       
                    yield return  serializer.Deserialize<T>(jsonreader);
                }
            
        }
    }
     

    class Person
    {
      public int Id {get;set;}
      public string  Name {get;set;}
    }

Try it online

output:

3

id: 123, Name: foo

id: 456, Name: bar

id: 789, Name: jar

Upvotes: 7

Steffen Timm
Steffen Timm

Reputation: 91

if your Json strings are separated by new lines you can iterate through all lines and parse them with the following code:

List<YourClass> objects = new List<YourClass>();
String[] lines = File.ReadAllLines("path\to\file.txt");
foreach (string line in lines)
{
    try
    {
        var obj = JsonDeserialize<YourClass>(line);
        objects.Add(obj);
    }
    catch (Exception) { }
}

If this doesn't help you, please post a sample file.

Upvotes: 1

CathalMF
CathalMF

Reputation: 10055

The only thing i can think of is to loop through each character and count brackets. When the bracket count is zero it will add the combined string to the list. At the end you will have a list of individual JSON strings.

public List<string> GetJsonItems()
{
    int BracketCount = 0;
    string ExampleJSON = new StreamReader(@"c:\Json.txt").ReadToEnd();
    List<string> JsonItems = new List<string>();
    StringBuilder Json = new StringBuilder();

    foreach (char c in ExampleJSON)
    {
        if (c == '{')
            ++BracketCount;
        else if (c == '}')
            --BracketCount;
        Json.Append(c);

        if (BracketCount == 0 && c != ' ')
        {
            JsonItems.Add(Json.ToString());
            Json = new StringBuilder();

        }
    }
    return JsonItems;    
}

EDIT: Changed the code to use StringBuilder and its much faster now. Parsed out a JSON file of 2MB almost instantly.

Upvotes: 1

raisedrev
raisedrev

Reputation: 11

You can also split your text file and iterate through each single JSON part.

Something like this:

void ReadJsonWithLinebreaks(string jsonFilePath)
{
        string jsonFileContent = File.ReadAllText(jsonFilePath);
        string[] jsonContentSplitted = jsonFileContent.Split(Environment.NewLine.ToCharArray());

        // ... iterate through array that contains your JSON content
}

Edit: Use File.ReadAllLines() instead of File.ReadAllText if your JSON-file comes with linebreaks.

Upvotes: 1

Jacob Lambert
Jacob Lambert

Reputation: 7679

I would recommend using the StreamReader class. This has a method ReadLine() that will return you json messages one at a time. You can either call your JsonDeserialize function as you read the file, or put all the messages into a list and deserialize them later.

List<MyClass> deserializedObjects = new List<MyClass>();
using(var reader = new StreamReader(pathToFile)){
    while(!reader.EndOfStream){
        deserializedObjects.Add(JsonDeserialize<MyClass>(reader.ReadLine()));
    }
}

Upvotes: 0

Related Questions