74

Here is the code:

        string s = "2012-08-08T01:54:45.3042880+00:00";

        JObject j1 = JObject.FromObject(new
        {
            time=s
        });

        Object o = j1["time"];

We can check that o is string and equals "2012-08-08T01:54:45.3042880+00:00"

Now we transfer j1.ToString() to another program, which is

       {
          "time": "2012-08-08T01:54:45.3042880+00:00"
       }

then at the other program, try to parse it back to JObject, which is

       JObject j2 = JObject.Parse(j1.ToString());

       Object o2 = j2["time"];

Now, if we check o2, o2's type is Date, o2.ToString() is 8/7/2012 9:54:45 PM.

My question is:

Is there is way to disable the Date deserialization for JObject.Parse , and just get the raw string?

Thanks in advance

liuhongbo
  • 2,051
  • 4
  • 22
  • 29

2 Answers2

101

When parsing from an object to JObject you can specify a JsonSerializer which instructs how to handle dates.

JObject.FromObject(new { time = s },
                   new JsonSerializer {
                          DateParseHandling = DateParseHandling.None
                   });

Unfortunately Parse doesn't have this option, although it would make sense to have it. Looking at the source for Parse we can see that all it does is instantiate a JsonReader and then passes that to Load. JsonReader does have parsing options.

You can achieve your desired result like this:

  using(JsonReader reader = new JsonTextReader(new StringReader(j1.ToString()))) {
    reader.DateParseHandling = DateParseHandling.None;
    JObject o = JObject.Load(reader);
  }

For background, see Json.NET interprets and modifies ISO dates when deserializing to JObject #862, specifically this comment from JamesNK: I have no plans to change it, and I would do it again if give the chance.

Jonathan
  • 6,939
  • 4
  • 44
  • 61
Samuel Neff
  • 73,278
  • 17
  • 138
  • 182
  • the program receive the whole json string which is {"time": "2012-08-08T01:54:45.3042880+00:00"}, so the program can not use JObject.FromObject to parse, has to use JObject.Parse to parse the string and JOjbect.Parse only take 1 parameter. – liuhongbo Aug 08 '12 at 02:34
  • @liuhongbo, weird that `Parse` doesn't provide the options that `FromObject` does. This peaked my curiosity so I downloaded the source and found a solution. I'll edit my answer. – Samuel Neff Aug 08 '12 at 02:45
  • 13
    thanks,Samuel Neff, that works perfect. Also, found another way to handle this issue: JsonSerializerSettings settings = new JsonSerializerSettings(); ; settings.DateParseHandling = DateParseHandling.None; JObject j2 = JsonConvert.DeserializeObject(j1.ToString(), settings); – liuhongbo Aug 08 '12 at 03:02
  • Thanks, this worked like a charm! Stopped me from implementing JsonReader.ToString and parsing the whole thing manually. – Dav Aug 10 '12 at 11:11
  • @Dav, glad it helped. This was a fun one to figure out. – Samuel Neff Aug 10 '12 at 17:56
  • THANK YOU! I'd spent a few hours figuring out my own workaround, only to find that in one of our environments, JObject.Parse treats dates as day/month/year instead of month/day/year, which broke everything in a hurry. You're a lifesaver. – Johnny Saxon Sep 11 '19 at 20:45
  • Perfect solution, thanks. Just a minor note: The readers are disposable, so the correct code should be: using var sr = new StringReader(j1.ToString()); using var reader = new JsonTextReader(sr); reader.DateParseHandling = DateParseHandling.None; var o = JObject.Load(reader); – NinjaCross Jun 23 '21 at 13:53
  • 1
    By default, JsonTextReader closes its wrapped text reader when it is disposed, so it shouldn't necessary to dispose the StringReader. To accurately replicate the behaviour of `JObject.Parse`, though, you should add `while(reader.Reader()) {}`. Otherwise, this will report success parsing a string that has content after the closing brace. – Andrew Bennet Nov 07 '22 at 12:31
  • (see https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Linq/JObject.cs) – Andrew Bennet Nov 07 '22 at 13:47
20

You can accomplish this using JsonConvert.DeserializeObject as well, by using JsonSerializerSettings:

string s = "2012-08-08T01:54:45.3042880+00:00";
string jsonStr = $@"{{""time"":""{s}""}}";

JObject j1 = JsonConvert.DeserializeObject<JObject>(jsonStr, new JsonSerializerSettings {DateParseHandling = DateParseHandling.None});
BobbyA
  • 2,090
  • 23
  • 41
  • 2
    And for, say, `JArray`, use `JsonConvert.DeserializeObject(jsonStr, new JsonSerializerSettings {DateParseHandling = DateParseHandling.None});` – dbc Oct 03 '19 at 15:53