Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ToString method with Formatting.None returns "null" instead of empty string for null values #2944

Open
The-Mojoo opened this issue Apr 16, 2024 · 2 comments

Comments

@The-Mojoo
Copy link

Source/destination types

JObject jsonObject = JObject.Parse(@"{ ""test"": null }");

Source/destination JSON

{ "test": null }

Expected behavior

value2 should both return an empty string because a null value should be converted to an empty string in both ToString(Formatting.None) and ToString(Formatting.Indented).

Actual behavior

value2 returns the string "null"

Steps to reproduce

JObject jsonObject = JObject.Parse(@"{ ""test"": null }");
var value = jsonObject["test"].ToString();
var value2 = jsonObject["test"].ToString(Formatting.None);
Console.WriteLine(value);  
Console.WriteLine(value2);  
@elgonzo
Copy link

elgonzo commented Apr 16, 2024

value2 should both return an empty string because a null value should be converted to an empty string in both ToString(Formatting.None) and ToString(Formatting.Indented).

No, none of the two ToString implementations should return an empty string for a json null value. Because obviously a null value is not equivalent to an empty string. (You might choose to interpret a null value to mean the same as an empty string, but that's your interpretation/business logic, not an equivalence intrinsic to null values.)

I am not saying that the current JValue.ToString() implementation is not having problems. A robust JValue.ToString() implementation would rather return strings that allow distinguishing between a json null value, a json string value "", the json string value "null", and json values of other types. Just replacing one form of ambiguity (representing both the json values null and "null" with the string "null") with a different flavor of ambiguity (representing both the json values null and "" with the string "") doesn't fix the issue underlying the limited JValue.ToString() implementation.

Note that JValue.ToString(Formatting, params JsonConverter[]) is not affected by this ambiguity. Because JValue.ToString(Formatting, params JsonConverter[]) produces the json representation of the value of the JValue instance, its current behavior is correct and unambiguous. It returns the string "null" for a json null value (the returned string being the json null literal), returns "\"\"" for a json empty string value, and returns "\"null\"" for a json string value "null" (note the double quotes included in the returned strings except when the json value is null, a number or a boolean).


Side note: If your intention is to work with the actual values represented by a JValue instance, don't use the ToString() methods. Instead, use the Value<T> extension method, e.g.:

var value = jsonObject["test"].Value<string?>();
Console.WriteLine(value ?? "<JSON_NULL_LITERAL>");

I am not associated with the Newtonsoft.Json project or its author/maintainer. I am just a user of the library like you (although these days i prefer STJ over Newtonsoft.Json).

@The-Mojoo
Copy link
Author

value2 should both return an empty string because a null value should be converted to an empty string in both ToString(Formatting.None) and ToString(Formatting.Indented).

No, none of the two ToString implementations should return an empty string for a json null value. Because obviously a null value is not equivalent to an empty string. (You might choose to interpret a null value to mean the same as an empty string, but that's your interpretation/business logic, not an equivalence intrinsic to null values.)

I am not saying that the current JValue.ToString() implementation is not having problems. A robust JValue.ToString() implementation would rather return strings that allow distinguishing between a json null value, a json string value "", the json string value "null", and json values of other types. Just replacing one form of ambiguity (representing both the json values null and "null" with the string "null") with a different flavor of ambiguity (representing both the json values null and "" with the string "") doesn't fix the issue underlying the limited JValue.ToString() implementation.

Note that JValue.ToString(Formatting, params JsonConverter[]) is not affected by this ambiguity. Because JValue.ToString(Formatting, params JsonConverter[]) produces the json representation of the value of the JValue instance, its current behavior is correct and unambiguous. It returns the string "null" for a json null value (the returned string being the json null literal), returns "\"\"" for a json empty string value, and returns "\"null\"" for a json string value "null" (note the double quotes included in the returned strings except when the json value is null, a number or a boolean).

Side note: If your intention is to work with the actual values represented by a JValue instance, don't use the ToString() methods. Instead, use the Value<T> extension method, e.g.:

var value = jsonObject["test"].Value<string?>();
Console.WriteLine(value ?? "<JSON_NULL_LITERAL>");

I am not associated with the Newtonsoft.Json project or its author/maintainer. I am just a user of the library like you (although these days i prefer STJ over Newtonsoft.Json).

Thank you for your detailed explanation and insights into JValue.ToString() behavior.

I completely agree with your point about the need for consistency in the ToString method. The inconsistency between ToString(Formatting.None) and ToString(Formatting.Indented) has indeed caused confusion and unexpected behavior in my subsequent logic, particularly in the empty value check.

In my view, when using ToString(), the current behavior of returning an empty string whether the value is present or null is exactly what I expect and want. My intention in using Formatting.None was simply to compress the JSON output for readability, not to change the value of the JSON representation.

I believe that the ToString method should consistently return the same result irrespective of the Formatting parameter, with Formatting only affecting the format of the output, not the value itself. I would also be okay with ToString() returning "null" to maintain consistency.

Thank you for suggesting the Value extension method as an alternative approach. I will consider using it for working directly with the underlying values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants