29

Is there a way to get the raw/original JSON value from a JToken?

The problem:

var data = JObject.Parse(@"{
    ""SimpleDate"":""2012-05-18T00:00:00Z"",
    ""PatternDate"":""2012-11-07T00:00:00Z""
}");

var value = data["SimpleDate"].Value<string>();

The value is now 05/18/2012 00:00:00 but I need the original string 2012-05-18T00:00:00Z.

Is there a way to get this original value? Also, I cannot change the way how the JObject is created (e.g. change settings), because it is passed as parameter into my class...

(Reference: The original NJsonSchema issue)

Rico Suter
  • 11,548
  • 6
  • 67
  • 93
  • I have a similar problem trying to parse an extended DateTime format (containing millesconds). To make the original question more clear: What if I have a free-text field like for a comment and the user enters something looking like a ISO DateTime? Would it be impossible to parse this string as is? – Nick Nov 11 '19 at 16:14

3 Answers3

28

You cannot get the original string, date strings are recognized and converted to DateTime structs inside the JsonReader itself. You can see this if you do:

Console.WriteLine(((JValue)data["SimpleDate"]).Value.GetType()); // Prints System.DateTime

You can, however, extract the dates in ISO 8601 format by doing:

var value = JsonConvert.SerializeObject(data["SimpleDate"]);
// value is "2012-05-18T00:00:00Z"

This will always output a JValue in a JSON-appropriate string format. Since your original dates are in this format, this may meet your needs.

(Honestly, I'm surprised JValue.ToString() outputs dates in non-ISO format, given that JObject.ToString() does output contained dates in ISO format.)

If you were able to change you settings while reading your JObject, you could use JsonSerializerSettings.DateParseHandling = DateParseHandling.None to disable DateTime recognition:

var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None };
var data = JsonConvert.DeserializeObject<JObject>(@"{
    ""SimpleDate"":""2012-05-18T00:00:00Z"",
    ""PatternDate"":""2012-11-07T00:00:00Z""
}", settings);

var value = data["SimpleDate"].Value<string>();

Debug.WriteLine(value); // Outputs 2012-05-18T00:00:00Z

There's no overload to JObject.Parse() that takes a JsonSerializerSettings, so use DeserializeObject. This setting eventually gets propagated to JsonReader.DateParseHandling.

Related Newtonsoft docs:

dbc
  • 104,963
  • 20
  • 228
  • 340
  • That's bad: I'm working on a JSON Schema validator, which takes a JObject and may validate such a date string with a regex pattern. This no longer matches when the value is converted into a DateTime... – Rico Suter Feb 01 '16 at 22:42
  • Maybe a bit of [XY](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) problem here? Could you leverage the fact that Json.NET has already recognized and parsed the date in your validator? There's no standard for dates in JSON after all, see http://www.newtonsoft.com/json/help/html/DatesInJSON.htm. – dbc Feb 01 '16 at 22:46
  • It seems that the only option is to disable date parsing when creating the JObject... here the original problem: https://github.com/NJsonSchema/NJsonSchema/issues/22 – Rico Suter Feb 01 '16 at 22:49
  • Its not an xy prob :-), i'm trying to implement a JSON Schema validator which takes a JObject. The JSON Schema may require more than only a date-time format for a property and may fail because of this automatic transformation... – Rico Suter Feb 01 '16 at 22:52
  • 1
    @RicoSuter - In that case I restored part of my original answer, in case it's useful. – dbc Feb 01 '16 at 22:56
7

There's a solution I found in Json.NET Disable the deserialization on DateTime:

JsonReader reader = new JsonTextReader(new StringReader(j1.ToString()));
reader.DateParseHandling = DateParseHandling.None;
JObject o = JObject.Load(reader);
Nick
  • 472
  • 3
  • 18
-4

another approach - that would work - Regex

SimpleDate(?:.*):(?:.*?)\"([0-9|-]{1,}T[0-9|:]+Z)

it is a regex pattern to extract the data you look for - you just wanted the string, so here it is . it is not the JSON parsing approach - but it indeed extracts the string.

here is a sample of how it works

Dan Kuida
  • 1,017
  • 10
  • 18