Reputation: 3613
I can't deserialize a JSON file which contains multiple objects of type Account
. Here is how I build my data.json
file. I have a List of Accounts List<Account>
which is serialize as usual. I separate each object in json file by adding a new line.
List<Account> listOfAccounts = new List<Account>();
if (listOfAccounts != null)
{
foreach (var item in listOfAccounts)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
string outputJSON = ser.Serialize(item);
// I added Environment.NewLine to separate each account in json file.
File.AppendAllText("data.json", outputJSON + Environment.NewLine);
}
}
Now, when I'm trying to retrieve all Accounts from the JSON file to List<Account>
I get an error: System.ArgumentException: 'Invalid JSON primitive:
Please help to find the solution, so I can get all objects from the JSON file.
private void JsonFileLoad()
{
if(File.Exists("data.json"))
{
String JSONtxt = File.ReadAllText("data.json");
JavaScriptSerializer ser = new JavaScriptSerializer();
// Not sure how to deserialize all lines into List<account>
List<Account> desirializedAccounts = ser.Deserialize<List<Account>>(JSONtxt);
}
}
I really appreciate any help you can provide.
Upvotes: 0
Views: 13891
Reputation: 2922
First of all, you should be serializing in standard json format. What you are doing is serializing the object and writing to file. It should have been, serialize the list altogether to json format. But assuming you might be having specific reason, I have given many possible solutions in different scenarios.
Note: I have used Newtonsoft.Json as this is fast and I find it very easy. http://www.newtonsoft.com/json
https://www.nuget.org/packages/newtonsoft.json/
Solutions:
//Class for testing object
public class Account
{
public int Id { get; set; }
public string Name { get; set; }
}
Solution 1: Recommended
/// <summary>
/// Serializing the list in single go
/// </summary>
public void Serialize()
{
List<Account> listOfAccounts = new List<Account>();
listOfAccounts.Add(new Account { Id = 1, Name = "First" });
listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
listOfAccounts.Add(new Account { Id = 3, Name = "Third" });
string outputJSON = Newtonsoft.Json.JsonConvert.SerializeObject(listOfAccounts, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(@"c:\temp\data.json", outputJSON + Environment.NewLine);
}
/// <summary>
/// Serializing the list, one by one object
/// Comma is appended to every object in json format
/// Finally, enclosed it with [ and ] to make it array of objects
/// </summary>
public void Serialize2()
{
List<Account> listOfAccounts = new List<Account>();
listOfAccounts.Add(new Account { Id = 1, Name = "First" });
listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
listOfAccounts.Add(new Account { Id = 3, Name = "Third" });
string outputJSON = "";
foreach(var item in listOfAccounts)
{
outputJSON += Newtonsoft.Json.JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented)+",";
}
File.WriteAllText(@"c:\temp\data.json", "["+outputJSON + "]");
}
/// <summary>
/// Read serialized data into list of objects
/// </summary>
public void DeSerialize()
{
if (File.Exists(@"c:\temp\data.json"))
{
String JSONtxt = File.ReadAllText(@"c:\temp\data.json");
var accounts = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<Account>>(JSONtxt);
}
}
Solution 2: as per your requirement
/// <summary>
/// Non standard json serialization (object one by one) Highly discouraged unless you have specific reason
/// Assuming the output will not have internal objects
/// </summary>
public void SerializeNonStandard()
{
List<Account> listOfAccounts = new List<Account>();
listOfAccounts.Add(new Account { Id = 1, Name = "First" });
listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
listOfAccounts.Add(new Account { Id = 3, Name = "Third" });
foreach (var item in listOfAccounts)
{
string outputJSON = Newtonsoft.Json.JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented);
File.AppendAllText(@"c:\temp\data-ns.json", outputJSON + Environment.NewLine);
}
}
/// <summary>
/// Deserializes the list in one by one fashion and appends to list
/// </summary>
public void DeSerializeNonStandard()
{
if (File.Exists(@"c:\temp\data-ns.json"))
{
List<Account> listOfAccounts = new List<Account>();
String JSONtxt = File.ReadAllText(@"c:\temp\data-ns.json");
//Capture JSON string for each object, including curly brackets
Regex regex = new Regex(@".*(?<=\{)[^}]*(?=\}).*", RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(JSONtxt);
foreach(Match match in matches)
{
string objStr = match.ToString();
Account account = Newtonsoft.Json.JsonConvert.DeserializeObject<Account>(objStr);
listOfAccounts.Add(account);
}
}
}
/// <summary>
/// Deserializes the non standard json to list of accounts
/// Splits the object strings, merges with comma and encloses with [] to make it array of objects format and deserializes
/// </summary>
public void DeSerializeNonStandardList()
{
if (File.Exists(@"c:\temp\data-ns.json"))
{
String JSONtxt = File.ReadAllText(@"c:\temp\data-ns.json");
//Capture JSON string for each object, including curly brackets
Regex regex = new Regex(@".*(?<=\{)[^}]*(?=\}).*", RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(JSONtxt);
string joinedJSON = string.Join(",", matches.Cast<Match>().Select(m => m.Value));
joinedJSON = string.Format("[{0}]", joinedJSON);
var listOfAccounts = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<Account>>(joinedJSON);
}
}
Upvotes: 4
Reputation: 667
You are serializing Account and not List of Account that's why deserialize it failed. Do you need to separate those account in new line? if so you could try add char '[' in the 1st and last char ']' in data.json.
Upvotes: 1