Reputation: 5459
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
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;}
}
output:
3
id: 123, Name: foo
id: 456, Name: bar
id: 789, Name: jar
Upvotes: 7
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
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
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
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