How to retrieve list in NewtownSoft json .net c# - c#

Whenever I try to get the list of items in NewtownSoft json with c# I get this exception "System.NullReferenceException" I don't know how to resolve this ,I tried my best but still getting this exception.
Here is the code and output.
public object Retrive(String FileName, Type DataType)
{
JObject obj = new JObject();
obj = null;
try
{
if (!File.Exists(CreateConfigutionFilePath(FileName)))
{
_ = File.Create(CreateConfigutionFilePath(FileName));
return obj;
}
if (new FileInfo(CreateConfigutionFilePath(FileName)).Length != 0)
{
JsonSerializer jsonSerializer = new JsonSerializer();
using (StreamReader textReader = new StreamReader(CreateConfigutionFilePath(FileName)))
{
JsonReader jsonReader = new JsonTextReader(textReader);
obj = jsonSerializer.Deserialize(jsonReader) as JObject;
}
}
}
catch (Exception e)
{
// TODO TO Add A PRompt
Console.WriteLine(e);
}
object DataObject = obj.ToObject(DataType);
return DataObject;
}
Output:
Exception thrown: 'System.NullReferenceException' in IMS.exe
System.NullReferenceException: Object reference not set to an instance of an object.
at IMS.Helpers.SettingHelper.Retrive(String FileName, Type DataType) in D:\ME\Visual Studio Projects\IMS\IMS\Helpers\SettingHelper.cs:line 168
at IMS.Pages.SettingsPages.InstituteSettings.RetriveConfig() in D:\ME\Visual Studio Projects\IMS\IMS\Page

Related

Proper way to rethrow a JsonConverter exception

I have the following setup for deserializing some json:
parsedResponse = JsonConvert.DeserializeObject<T>(
json,
new JsonSerializerSettings
{
Error = (object sender, ErrorEventArgs args) =>
{
throw new MyParseException($"Parse error: {args.ErrorContext.Error.Message}");
},
Converters =
{
new MyItemConverter(),
new BoolConverter(),
new UnixDateTimeConverter(),
new NullableIntConverter(),
new UriConverter()
}
}
);
In one case, json has a bunch of null values (like "title" : null, etc) which causes a NullReferenceException in one of my converters. But throwing MyParseException in the error handler causes
System.InvalidOperationException: Current error context error is different to requested error.
I think I could do this instead:
try
{
parsedResponse = JsonConvert.DeserializeObject<T>(
json,
new JsonSerializerSettings
{
Converters =
{
new MyItemConverter(),
new BoolConverter(),
new UnixDateTimeConverter(),
new NullableIntConverter(),
new UriConverter()
}
}
);
}
catch (Exception ex)
{
throw new MyParseException($"Parse error: {ex.Message}");
}
But is there a better way? (Maybe something more similar to my original solution that doesn't cause the error context issue?)
Based on the Newtonsoft example here. I've ended up doing the following:
List<MyParseException> errors = new List<MyParseException>();
T parsedResponse = JsonConvert.DeserializeObject<T>(
json,
new JsonSerializerSettings
{
Error = (object sender, ErrorEventArgs args) =>
{
errors.Add(new MyParseException(String.Format("Parse error: {0}", args.ErrorContext.Error.Message), args.ErrorContext.Error));
args.ErrorContext.Handled = true;
},
Converters =
{
new MyItemConverter(),
new BoolConverter(),
new UnixDateTimeConverter(),
new NullableIntConverter(),
new UriConverter()
}
}
);
if (errors.Count == 1)
{
MyParseException firstException = errors[0];
firstException.Data["json"] = json;
throw firstException;
}
else if (errors.Count > 1)
{
AggregateException ex = new AggregateException("Unable to parse json. See innner exceptions and exception.Data[\"json\"] for details", errors);
ex.Data["json"] = json;
throw ex;
}

Can I deserialize a JSON text until error or end with Newtonsoft parser? [duplicate]

My json file is mostly an array that contain objects but the list is incomplete, so I can't use the last entry. I would like to deserialize the rest of the file while discarding the last invalid entry
[ { "key" : "value1" }, { "key " : "value2"}, { "key
Please tell me if there is a way using Newtonsoft.Json library, or do I need some preprocessing.
Thank you!
Looks like on Json.NET 8.0.3 you can stream your string from a JsonTextReader to a JTokenWriter and get a partial result by catching and swallowing the JsonReaderException that gets thrown when parsing the truncated JSON:
JToken root;
string exceptionPath = null;
using (var textReader = new StringReader(badJson))
using (var jsonReader = new JsonTextReader(textReader))
using (JTokenWriter jsonWriter = new JTokenWriter())
{
try
{
jsonWriter.WriteToken(jsonReader);
}
catch (JsonReaderException ex)
{
exceptionPath = ex.Path;
Debug.WriteLine(ex);
}
root = jsonWriter.Token;
}
Console.WriteLine(root);
if (exceptionPath != null)
{
Console.WriteLine("Error occurred with token: ");
var badToken = root.SelectToken(exceptionPath);
Console.WriteLine(badToken);
}
This results in:
[
{
"key": "value1"
},
{
"key ": "value2"
},
{}
]
You could then finish deserializing the partial object with JToken.ToObject. You could also delete the incomplete array entry by using badToken.Remove().
It would be better practice not to generate invalid JSON in the first place though. I'm also not entirely sure this is documented functionality of Json.NET, and thus it might not work with future versions of Json.NET. (E.g. conceivably Newtonsoft could change their algorithm such that JTokenWriter.Token is only set when writing is successful.)
You can use the JsonReader class and try to parse as far as you get. Something like the code below will parse as many properties as it gets and then throw an exception. This is of course if you want to deserialize into a concrete class.
public Partial FromJson(JsonReader reader)
{
while (reader.Read())
{
// Break on EndObject
if (reader.TokenType == JsonToken.EndObject)
break;
// Only look for properties
if (reader.TokenType != JsonToken.PropertyName)
continue;
switch ((string) reader.Value)
{
case "Id":
reader.Read();
Id = Convert.ToInt16(reader.Value);
break;
case "Name":
reader.Read();
Name = Convert.ToString(reader.Value);
break;
}
}
return this;
}
Code taken from the CGbR JSON Target.
the second answer above is really good and simple, helped me out!
static string FixPartialJson(string badJson)
{
JToken root;
string exceptionPath = null;
using (var textReader = new StringReader(badJson))
using (var jsonReader = new JsonTextReader(textReader))
using (JTokenWriter jsonWriter = new JTokenWriter())
{
try
{
jsonWriter.WriteToken(jsonReader);
}
catch (JsonReaderException ex)
{
exceptionPath = ex.Path;
}
root = jsonWriter.Token;
}
return root.ToString();
}

JsonConvert.Deserialize with truncated JSON? [duplicate]

My json file is mostly an array that contain objects but the list is incomplete, so I can't use the last entry. I would like to deserialize the rest of the file while discarding the last invalid entry
[ { "key" : "value1" }, { "key " : "value2"}, { "key
Please tell me if there is a way using Newtonsoft.Json library, or do I need some preprocessing.
Thank you!
Looks like on Json.NET 8.0.3 you can stream your string from a JsonTextReader to a JTokenWriter and get a partial result by catching and swallowing the JsonReaderException that gets thrown when parsing the truncated JSON:
JToken root;
string exceptionPath = null;
using (var textReader = new StringReader(badJson))
using (var jsonReader = new JsonTextReader(textReader))
using (JTokenWriter jsonWriter = new JTokenWriter())
{
try
{
jsonWriter.WriteToken(jsonReader);
}
catch (JsonReaderException ex)
{
exceptionPath = ex.Path;
Debug.WriteLine(ex);
}
root = jsonWriter.Token;
}
Console.WriteLine(root);
if (exceptionPath != null)
{
Console.WriteLine("Error occurred with token: ");
var badToken = root.SelectToken(exceptionPath);
Console.WriteLine(badToken);
}
This results in:
[
{
"key": "value1"
},
{
"key ": "value2"
},
{}
]
You could then finish deserializing the partial object with JToken.ToObject. You could also delete the incomplete array entry by using badToken.Remove().
It would be better practice not to generate invalid JSON in the first place though. I'm also not entirely sure this is documented functionality of Json.NET, and thus it might not work with future versions of Json.NET. (E.g. conceivably Newtonsoft could change their algorithm such that JTokenWriter.Token is only set when writing is successful.)
You can use the JsonReader class and try to parse as far as you get. Something like the code below will parse as many properties as it gets and then throw an exception. This is of course if you want to deserialize into a concrete class.
public Partial FromJson(JsonReader reader)
{
while (reader.Read())
{
// Break on EndObject
if (reader.TokenType == JsonToken.EndObject)
break;
// Only look for properties
if (reader.TokenType != JsonToken.PropertyName)
continue;
switch ((string) reader.Value)
{
case "Id":
reader.Read();
Id = Convert.ToInt16(reader.Value);
break;
case "Name":
reader.Read();
Name = Convert.ToString(reader.Value);
break;
}
}
return this;
}
Code taken from the CGbR JSON Target.
the second answer above is really good and simple, helped me out!
static string FixPartialJson(string badJson)
{
JToken root;
string exceptionPath = null;
using (var textReader = new StringReader(badJson))
using (var jsonReader = new JsonTextReader(textReader))
using (JTokenWriter jsonWriter = new JTokenWriter())
{
try
{
jsonWriter.WriteToken(jsonReader);
}
catch (JsonReaderException ex)
{
exceptionPath = ex.Path;
}
root = jsonWriter.Token;
}
return root.ToString();
}

Error: Not all code paths return a value [duplicate]

This question already has answers here:
C# compiler error: "not all code paths return a value"
(9 answers)
Closed 8 years ago.
Why it happens? Here is my code to read dictionary from bin file
public static object LoadObject()
{
try
{
if (File.Exists("D://my.bin"))
{
FileStream stream = File.OpenRead("D://my.bin");
BinaryFormatter formatter = new BinaryFormatter();
Dictionary<int, Question> deserializedObject = (Dictionary<int, Question>)formatter.Deserialize(stream);
stream.Close();
return deserializedObject;
}
}
catch
{
}
}
Your method is suppose to return an object of type object, but you are only returning inside the try block and that too from inside an if statement. So if your condition fails, your method will not return anything. Also if there is an exception in try block, before returning the object then your method would fail to return anything. That is why you are getting the error. You can fix that by returning null from outside of try / catch block.
public static object LoadObject()
{
try
{
if (File.Exists("D://my.bin"))
{
FileStream stream = File.OpenRead("D://my.bin");
BinaryFormatter formatter = new BinaryFormatter();
Dictionary<int, Question> deserializedObject = (Dictionary<int, Question>)formatter.Deserialize(stream);
stream.Close();
return deserializedObject;
}
}
catch(Exception ex)
{
//log exception
return null;
}
return null;
}
Although this will will fix your error, but you should look for other option like throwing an exception if the file is not found, or returning an error object.
You need a return also if your code raises an exception or if the condition File.Exists is not met
However, as is, there is no point in catching the exception. If you don't do anything with it, let it bubble at the upper level
public static object LoadObject()
{
if (File.Exists("D://my.bin"))
{
FileStream stream = File.OpenRead("D://my.bin");
BinaryFormatter formatter = new BinaryFormatter();
Dictionary<int, Question> deserializedObject = (Dictionary<int, Question>)formatter.Deserialize(stream);
stream.Close();
return deserializedObject;
}
else
throw FileNotFoundException("There is no file named", "D:\\my.bin");
}
As the error message suggests, all the code paths must return a value. You have two conditions where no value is returned:
If the file does not exist.
If an exception is thrown.
Change the code to:
try
{
if (File.Exists("D://my.bin"))
{
...
return deserializedObject;
}
}
catch
{
}
return null; // Or return an empty dictionary with:
// return new Dictionary<int, Question>();
You can try this
public static object LoadObject()
{
try
{
if (File.Exists("D://my.bin"))
{
FileStream stream = File.OpenRead("D://my.bin");
BinaryFormatter formatter = new BinaryFormatter();
Dictionary<int, Question> deserializedObject = (Dictionary<int, Question>)formatter.Deserialize(stream);
stream.Close();
return deserializedObject;
}
}
catch
{
return null;
}
return null;
}

returning a Tuple with a null item

I have some code that looks like this:
public Tuple<bool, SomeObjectModel> CheckIfJsonIsValid(string IncomingJson)
{
SomeObjectModel TheObjectModel = new SomeObjectModel();
JavascriptSerializer TheSerializer = new JavascriptSerializer();
.....
try
{
TheObjectModel = TheSerializer.Deserialize<SomeObjectModel>(IncomingJson);
}
catch
{
return new Tuple<bool, SomeObjectModel>(false, null); //question here
}
.....
return new Tuple<bool, SomeObjectModel>(true, TheObjectModel);
}
The calling method first check the returning tuple's Item1, and if it's false, ends its process.
Is it better practice a) to return a null value in the Tuple or b) to return a new and fresh instance of SomeObjectModel? Are there any performance implications?
Thanks for your suggestions.
Let me suggest three alternative solutions:
ParseJsonIfValid: If deserializing works, TheObjectModel is always non-null. Thus, there is no need for the boolean:
public SomeObjectModel ParseJsonIfValid(string IncomingJson)
{
JavascriptSerializer TheSerializer = new JavascriptSerializer();
.....
try
{
return TheSerializer.Deserialize<SomeObjectModel>(IncomingJson);
}
catch
{
return null;
}
}
In the calling function simply check whether the return value is null or not.
ParseJson: If the JSON is usually valid, and invalid JSON is a sign of something gone terribly wrong, just throw an exception:
public SomeObjectModel ParseJson(string IncomingJson)
{
JavascriptSerializer TheSerializer = new JavascriptSerializer();
.....
try
{
return TheSerializer.Deserialize<SomeObjectModel>(IncomingJson);
}
catch (Exception e)
{
throw new TheServerSentRubbishException(e);
}
}
Be sure to include the inner ("real") exception, so that the calling function can log the real cause of the error for debugging purposes.
TryParseJson: If null can be a valid deserialization, you can use the following pattern, which has the advantage of being consistent with the TryParse methods of the .NET framework:
public bool TryParseJson(string IncomingJson, out SomeObjectModel theObjectModel)
{
JavascriptSerializer TheSerializer = new JavascriptSerializer();
.....
try
{
theObjectModel = TheSerializer.Deserialize<SomeObjectModel>(IncomingJson);
return true;
}
catch (Exception e)
{
return false;
}
}

Categories