Can the result of JsonSerializer.Deserialize ever be null? - c#

The return type shown in the docs for the JsonSerializer.Deserialize method all show the return type as nullable.
If you look at the deserialisation examples in the MS docs, you see that they are inconsistent, in that the first and third specify the return type as nullable...
WeatherForecast? weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString);
...whereas the second example misses off the ?, meaning it's non-nullable.
By experimenting, it seems that as long as you supply valid JSON (otherwise you get an exception), then the return value is always a non-null object of the specified type. If the property names don't match, then the returned object will have default values for those properties, but you never get a null reference - or at least, I couldn't find a way.
Anyone able to clarify? Is there a situation in which the method can return null, without throwing an exception? If not, why are the return types specified as nullable?
Thanks

Yes, parsing valid JSON "null" with a JSON serializer have to return null.
WeatherForecast? weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>("null");
Note that other valid JSON strings like "123", "\"bob\"", "[]" should cause an exception because none of them represent a valid object.

Related

C# Error converting null value to type double during deserialization

Receiving this error message:
Error converting value {null} to type 'System.Double'. Path 'rings[0][0][3]', line 1, position 79.
The code producing the error:
string polygonGeom = geometry.ToJson();
GeoJSONClass.PolygonGeometry polygonGeometry = JsonConvert.DeserializeObject<GeoJSONClass.PolygonGeometry>(polygonGeom);
why can it not Deserialize the JSON produced?
As mentioned in the comment it is hard to answer without specific Type details. From the error it seems you are trying to map a value that can be null to a field declared as double.
Value types cannot be null. But if you need it to be null (maybe for optional fields) then use a nullable value type.
But since you are using an external type, make sure you handle the null values before passing it to sonConvert.DeserializeObject<GeoJSONClass.PolygonGeometry>(polygonGeom);

Reference types vs Nullable types ToString()

Could someone please be kind enough to explain why calling ToString() on an empty reference type causes an exception (which in my mind makes perfect sense, you cant invoke a method on nothing!) but calling ToString() on an empty Nullable(Of T) returns String.Empty? This was quite a surprise to me as I assumed the behaviour would be consistent across types.
Nullable<Guid> value = null;
Stock stock = null;
string result = value.ToString(); //Returns empty string
string result1 = stock.ToString(); //Causes a NullReferenceException
Nullable<T> is actually a struct that has some compiler support and implementation support to behave like a null without actually being null.
What you are seeing is the collision between the implementation allowing you to treat it naturally as a null as you would any other reference type, but allowing the method call to happen because the Nullable<T> isn't actually null, the value inside it is null.
Visually it looks like it shouldn't work, this is simply because you cannot see what is done in the background for you.
Other such visual trickery can be seen when you call an extension method on a null reference type... the call works (against visual expectation) because under the hood it is resolved into a static method call passing your null instance as a parameter.
How does a Nullable<T> type work behind the scenes?
Nullable is a value type and the assignment to null causes it to be initialized with Value=null and HasValue=false.
Further, Nullable.ToString() is implement as follows:
public override string ToString()
{
if (!this.HasValue)
{
return "";
}
return this.value.ToString();
}
So what you are seeing is expected.
It is a bit tricky with nullable types. When you set it to null it is actualy not null cause it is not reference type (it is value type). When you initialize such variable with null it creates new sctructure instance where HasValue property is false and it's Value is null, so when you call ToString method it works well on structure instance.
The exception raised by calling default(object).ToString() is called NullReferenceException for a reason, it's calling a method on a null reference. default(int?) on the other hand, is not a null reference, because it's not a reference; it is a value type with a value that is equivalent to null.
The big practical point, is that if this was done, then the following would fail:
default(int?).HasValue // should return false, or throw an exception?
It would also screw-up the way we have some ability to mix nullables and non-nullables:
((int?)null).Equals(1) // should return false, or throw an exception?
And the following becomes completely useless:
default(int?).GetValueOrDefault(-1);
We could get rid of HasValue and force comparison with null, but then what if the equality override of the value-type that is made nullable can return true when compared to null in some cases. That may not be a great idea, but it can be done and the language has to cope.
Let's think back to why nullable types are introduced. The possibility that a reference type can be null, is inherent in the concept of reference types unless effort is taken to enforce non-nullability: Reference types are types that refer to something, and that implies the possibility of one not referring to anything, which we call null.
While a nuisance in many cases, we can make use of this in a variety of cases, such as representing "unknown value", "no valid value" and so on (we can use it for what null means in databases, for example).
At this point, we've given null a meaning in a given context, beyond the simple fact that a given reference doesn't refer to any object.
Since this is useful, we could therefore want to set an int or DateTime to null, but we can't because they aren't types that refer to something else, and hence can't be in a state of not referring to anything any more than I as a mammal can lose my feathers.
The nullable types introduced with 2.0 give us a form of value types that can have the semantic null, through a different mechanism than that of reference types. Most of this you could code yourself if it didn't exist, but special boxing and promotion rules allow for more sensible boxing and operator use.
Okay. Now let's consider why NullReferenceExceptions happen in the first place. Two are inevitable, and one was a design decision in C# (and doesn't apply to all of .NET).
You try to call a virtual method or property, or access a field on a null reference. This has to fail, because there's no way to look up what override should be called, and no such field.
You call a non-virtual method or property on a null reference which in turn calls a virtual method or property, or accesses a field. This is obviously a variant on point one, but the design decision we're coming to next has the advantage of guaranteeing this fails at the start, rather than part-way through (which could be confusing and have long-term side-effects).
You call a non-virtual method or property on a null reference which does not call a virtual method or property, or access a field. There's no inherent reason why this should not be allowed, and some languages allow it, but in C# they decided to use callvirt rather than call to force a NullReferenceException for the sake of consistency (can't say I agree, but there you go).
None of these cases apply in any way to a nullable value type. It is impossible to put a nullable value type into a condition in which there is no way to know which field or method override to access. The whole concept of NullReferenceException just doesn't make sense here.
In all, not throwing a NullReferenceException is consistent with the other types - types through it if and only if a null reference is used.
Note that there is a case where calling on a null nullable-type throws, it does so with GetType(), because GetType() is not virtual, and when called on a value-type there is always an implied boxing. This is true of other value types so:
(1).GetType()
is treated as:
((object)1).GetType()
But in the case of nullable types, boxing turns those with a false HasValue into null, and hence:
default(int?).GetType()
being treated as:
((object)default(int?)).GetType()
which results in GetType() being called on a null object, and hence throwing.
This incidentally brings us to why not faking NullReferenceType was the more sensible design decision - people who need that behaviour can always box. If you want it to through then use ((object)myNullableValue).GetString() so there's no need for the language to treat it as a special case to force the exception.
EDIT
Oh, I forgot to mention the mechanics behind NullReferenceException.
The test for NullReferenceException is very cheap, because it mostly just ignores the problem, and then catches the exception from the OS if it happens. In other words, there is no test.
See What is the CLR implementation behind raising/generating a null reference exception? and note how none of that would work with nullable value types.
If you investigate Nullable<> definition, there is an override ToString definition. In this function, ToString is overriden to return String.Empty.
// Summary:
// Returns the text representation of the value of the current System.Nullable<T>
// object.
//
// Returns:
// The text representation of the value of the current System.Nullable<T> object
// if the System.Nullable<T>.HasValue property is true, or an empty string ("")
// if the System.Nullable<T>.HasValue property is false.
public override string ToString();
On the otherhand, Stock is a custom class, which I assume ToString is not overriden. Thus it returns NullReferenceException since it uses default behaviour.
As per MSDN Remarks
Guid.ToSTring() method Returns a string representation of the
value of this Guid instance, according to the provided format
specifier.
As per MSDN Remarks on Nullable
A type is said to be nullable if it can be assigned a value or can be
assigned null, which means the type has no value whatsoever.
Consequently, a nullable type can express a value, or that no value
exists. For example, a reference type such as String is nullable,
whereas a value type such as Int32 is not. A value type cannot be
nullable because it has enough capacity to express only the values
appropriate for that type; it does not have the additional capacity
required to express a value of null.

linq-to-sql SingleOrDefault return when null

I'm writing a linq-to-sql query and I'm loading an ID (a bigint in the database and a long in my code) from a table, something like this:
var SomeQuery = (from x in ...
select x.ID).SingleOrDefault();
When I get the result, I use SingleOrDefault in case the return is empty. Does that mean that if the result is empty the SomeQuery variable will be 0 or null?
Thanks.
If you look the documenation for SingleOrDefault
Returns the only element of a sequence, or a default value if the
sequence is empty; this method throws an exception if there is more
than one element in the sequence.
It cleary states that if the sequence is empty it will return the default value which for long and bigint is 0. Why explained below
Documenation for default keyword states
In generic classes and methods, one issue that arises is how to assign
a default value to a parameterized type T when you do not know the
following in advance:
Whether T will be a reference type or a value type.
If T is a value type, whether it will be a numeric value or a struct.
Given a variable t of a parameterized type T, the statement t = null
is only valid if T is a reference type and t = 0 will only work for
numeric value types but not for structs. The solution is to use the
default keyword, which will return null for reference types and zero
for numeric value types.
Default is returned if no element found.(default value of int is 0)
Value is returned if one is found.
Exception is thrown if more than one is found.

nullable object must have a value in Linq

I use following Linq To Entitiy To get the first and only record of my 'siteconfig' Entity :
var site = unitofwork.SiteConfigRepository.Get().FirstOrDefault();
But when my application comes to the following code, throws 'nullable object must have a value' :
if (site!= null) { TimeSpan span = DateTime.Now.Subtract((DateTime)site.logindDate ); }
And the only nullable type in my entity is a property called logindDate and is of type DateTime.
Any one help me out?
Try something like this:
if (site!= null)
{
if (site.loginDate.HasValue)
{ TimeSpan span = DateTime.Now.Subtract((DateTime)site.logindDate.Value ); }
}
You are not checking for a null loginDate and I suspect that may be the problem. Remember, when you have a nullable type, you need to check for HasValue, and then get the value from the Value property.
IEnumerable.FirstOrDefault() returns the first element of the enumerable, or default(T) (which is generally null, unless T is a value type) if there is no element in the list. Most probably your Get() returns an empty enumerable.
On a related matter (if indeed it is what happens), if you're sure that there is always one and only one element returned by a list, you should use Single() (because then you will have an exception thrown at that line) or test it against null just after the FirstOrDefault(). I think it's best having exceptions throwing or handling at the source of the unexpected behavior, and not several lines later.

String casts in .NET

Why is there so may ways to convert to a string in .net? The ways I have seen are .ToString, Convert.ToString() and (string). What is the Difference.
Convert.ToString(obj)
Converts the specified value to its equivalent String representation. Will return String.Empty if specified value is null.
obj.ToString()
Returns a String that represents the current Object. This method returns a human-readable string that is culture-sensitive. For example, for an instance of the Double class whose value is zero, the implementation of Double.ToString might return "0.00" or "0,00" depending on the current UI culture. The default implementation returns the fully qualified name of the type of the Object.
This method can be overridden in a derived class to return values that are meaningful for that type. For example, the base data types, such as Int32, implement ToString so that it returns the string form of the value that the object represents. Derived classes that require more control over the formatting of strings than ToString provides must implement IFormattable, whose ToString method uses the current thread's CurrentCulture property.
(string)obj
It's a cast operation, not a function call. Use it if you're sure that the object is of type string OR it has an implicit or explicit operator that can convert it to a string. Will return null if the object is null AND of type String or of type which implements custom cast to string operator. See examples.
obj as string
Safe cast operation. Same as above, but instead of throwing an exception it will return null if cast operation fails.
Hint: Don't forget to use CultureInfo with obj.ToString() and Convert.ToString(obj)
Example:
12345.6D.ToString(CultureInfo.InvariantCulture); // returns 12345.6
12345.6D.ToString(CultureInfo.GetCultureInfo("de-DE")); // returns 12345,6
Convert.ToString(12345.6D, CultureInfo.InvariantCulture); // returns 12345.6
Convert.ToString(12345.6D, CultureInfo.GetCultureInfo("de-DE")); // 12345,6
Convert.ToString(test); // String.Empty, "test" is null and it's type
// doesn't implement explicit cast to string oper.
Convert.ToString(null); // null
(string) null; // null
(string) test; // wont't compile, "test" is not a string and
// doesn't implement custom cast to string operator
(string) test; // most likely NullReferenceException,
// "test" is not a string,
// implements custom cast operator but is null
(string) test; // some value, "test" is not a string,
// implements custom cast to string operator
null as string; // null
Here is an example of custom cast operator:
public class Test
{
public static implicit operator string(Test v)
{
return "test";
}
}
.ToString() can be called from any object. However, if the type you call it on doesn't have a good implementation the default is to return the type name rather than something meaningful about the instance of that type. This method is inherited from the base Object type, and you can overload it in your own types to do whatever you want.
(string) is a cast, not a function call. You should only use this if the object you need already is a string in some sense, or if you know there is a good implicit conversion available (like from int). This will throw an exception is the object cannot be converted (including when the object is null)
as string is another way to write (string), but it differs in that it returns null rather than throwing an exception if the cast fails.
Convert.ToString() attempts to actually convert the argument into a string. This is the best option if you don't really know much about the argument. It can be slow because it has to do a lot of extra work to determine what kind of results to return, but that same work also makes it the most robust option when you don't know very much about the argument. If nothing else is available, it will fall back to calling the argument's .ToString() method.
String.Format The string class' .Format method can also be used to convert certain types to strings, with the additional advantage that you have some control over what the resulting string will look like.
Serialization This is a little more complicated, but .Net includes a couple different mechanisms for converting objects into a representation that can be safely stored and re-loaded from disk or other streaming mechanism. That includes a binary formatter, but most often involves converting to a string in some format or other (often xml). Serialization is appropriate when you want to later convert the your string back into it's originating type, or if you want a complete representation of a complex type.
Convert.ToString() will return an empty string if the object is null .ToString and (String) will throw an exception. Convert.ToString will internally call .ToString() if the value is null it will return an empty String.
object.ToString() is the most basic way of retrieving a string representation of an object, and can be specifically implemented by the object.
Convert.ToString() expands on that and provides some specific overloads for primitive types (char, byte, int, double, etc.) that allow for some more type-specific functionality (like base conversion, for example)
(string) is a casting operator, and will only work if the type is either a string or has an implicit or explicit operator that can convert it to a string. Otherwise you'll get an InvalidCastException
Don't forget as string
ToString() is a method of object, and it will always work on a non-null reference, so you'll get something, but whether that something is what you want, is a different story.
Convert.ToString() will yield the same result in most cases, but isn't as flexible as Object.ToString() as you can't pass custom formatting rules.
(string) will cast your object to string, and if it isn't a string then you'll get an InvalidCastException().
Think.
ToString is a virtual method, and each type can implement it however it wants. Also System.Object provides default implementations so that it always succeeds.
Convert.ToString works only with nulls as well and allows you to use IFormat provier as noted in the comment.
Casting to string requires object to implement casting operator. Again, types can implement it however they like, but most types do not, so you may get an exception here.
Use .ToString as your best option.
.ToString() is an instance method which asks the object for its string representation. When the object is null, this will throw a exception.
(string) is a cast to the string type, which isn't a very good idea in most cases except for simple data types, since it can break (throw an exception) when it's null or an invalid cast
Convert.ToString() does a bit more checking than a simple cast, giving a more robust alternative to the cast. It will return the empty string when the object is null.
Not to nitpick but null is a valid value for a String object. Therefore (string) null does not throw any exceptions. Try it for yourselves:
using System;
namespace Test
{
class Program
{
public static void Main(string[] args)
{
string s = (string) null;
Console.WriteLine(s);
}
}
}

Categories

Resources