JamesNK / Newtonsoft.Json

Json.NET is a popular high-performance JSON framework for .NET
https://www.newtonsoft.com/json
MIT License
10.73k stars 3.25k forks source link

the original string is not preserved #2819

Open JOEJKJK opened 1 year ago

JOEJKJK commented 1 year ago

Source/destination types

Sub Main
Dim s="{""aaa"":""2001-02-17T12:12:12"",""bbb"":{""ccc"":""2001-02-17T12:12:12""}}".dump
Dim a=JsonConvert.DeserializeObject(Of testj)(s).dump
Dim b=a.bbb.ToObject(Of testj2).dump

End Sub
Class testj
    Property aaa As String
    Property bbb As Linq.jobject
End Class
Class testj2
    Property ccc As String
End Class

Source/destination JSON

{"aaa":"2001-02-17T12:12:12","bbb":{"ccc":"2001-02-17T12:12:12"}}

Expected behavior

the property ccc is 2001-02-17T12:12:12

Actual behavior

the property ccc is 02/17/2001 12:12:12

螢幕擷取畫面 2023-02-19 211030

Steps to reproduce

// Your calls to Newtonsoft.Json here
elgonzo commented 1 year ago

As a workaround, set the DateParseHandling setting to DateParseHandling.None, like for example (C# syntax)

var a = JsonConvert.DeserializeObject<testj>(s, new JsonSerializerSettings { DateParseHandling = DateParseHandling.None });

(The default for this setting is DateParseHandling.DateTime, hence the observed behavior...)

JOEJKJK commented 1 year ago

you are right, but when you call the toString on the bbb property, you get: { "ccc": "2001-02-17T12:12:12" } so you have saved the original data somewhere, isnt it more nature to deserialize it directly to the .net object(since the signature of the property is string, not datetime) rather than converting it to something else(and this behavior doesnt consist with the first deserialization by calling JsonConvert.DeserializeObject), because this is usually not the author would expect to happen, and it may create a security issue if the author doesnt aware that his string is silently converted to datetime.

elgonzo commented 1 year ago

you call the toString on the bbb property

That's calling ToString() on the JObject representing the {""ccc"":""2001-02-17T12:12:12""} json object. At that point, the ccc property isn't directly accessed.

Try applying ToString() to a.bbb["ccc"] instead. This will access the ccc property value, which will lead to it being interpreted as a DateTime (due to the default DateParseHandling setting), which then in turn is then converted back into a string using whatever locale/culture setting being active for the executing thread at that time.

so you have saved the original data somewhere, isnt it more nature to deserialize it directly to the .net object(since the signature of the property is string, not datetime) rather than converting it to something else [...]

Yes, absolutely. And the author of Newtonsoft.Json acknowledged as much elsewhere in another issue thread:

The right behavior is to not convert the value to anything when parsing and leave it as a char[] until a .NET type is requested. But that is a design decision that needed to be made in 2007. It's too late to change it now.

As the author notes, this has been long established behavior, however, and with the widespread adoption of Newtonsoft.Json this is pretty much locked-in, as it seems...

JOEJKJK commented 1 year ago

ok, I think Ill learn to accept that. many thanks for concerning my oppion.