Cannot deserialize JSON with both UTC and non UTC formatted datetimes - c#

I am reading in JSON from an external API. The datetime values are formatted differently for some reason and I cant get it to automatically deserialize into my object using Newtonsoft.Json.
For example, suppose the following is my JSON (the only diff in the two datetime values is the first one ends in 'Z' and the second does not):
string json = "{ \"DateTime1\" : \"20131101T000000Z\", \"DateTime2\" : \"20131101T000000\" }";
Then I need to parse the 2 datetime fields into an object containing DateTime1 and DateTime2 properties like this:
class Foo
{
public DateTime DateTime1 { get; set; }
public DateTime DateTime2 { get; set; }
}
My deserialization code looks like this:
var format = "yyyyMMddThhmmssZ"; // your datetime format
var dateTimeConverter = new IsoDateTimeConverter { DateTimeFormat = format };
JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
serializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
serializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
serializerSettings.DateParseHandling = DateParseHandling.DateTimeOffset;
string json = "{ \"DateTime1\" : \"20131101T000000Z\", \"DateTime2\" : \"20131101T000000\" }";
try
{
var serializer = JsonSerializer.Create(serializerSettings);
var o3 = JsonConvert.DeserializeObject<Foo>(json, dateTimeConverter);
}
catch(Exception ex)
{
var x = ex.Message.ToString();
}
return;
Running the code above gives me:
String was not recognized as a valid DateTime
Any help would be greatly appreciated!

Your datetime format string for IsoDateTimeConverter doesn't look correct, try to update it per following
var dateTimeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyyMMddTHHmmssK" };
According to Custom date and time format strings,
K format specifier is used for time zone information, there is no Z format specifier

Related

How to avoid JObject.Parse parsing a DateTime, and instead just get the raw string?

I have a JSON data like below, when I read the DateTime tag, it is internally converted to {2/11/2022 6:56:17 AM}. I need data to be read in the string format, same as data available in the JSON
Code Snippet:
JObject jsonObject = JObject.Parse(jsonText);
var dateTime = jsonObject["LastModified"]["DateTime"]; // output = {2/11/2022 6:56:17 AM}, but i need "2022-02-11T06:56:17.143Z".
{"LastModified": {
"Username": "Philips Administrator",
"DateTime": "2022-02-11T06:56:17.143Z"
}
}
As others point out a DateTime has no format. When you convert it to a string you can format it however you like. If you really, really want to treat it as a string, you can do as Jon Skeet suggests:
var jsonText = #"{""LastModified"": {
""Username"": ""Philips Administrator"",
""DateTime"": ""2022-02-11T06:56:17.143Z""
}
}";
var settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None
};
JObject jsonObject = (JObject)JsonConvert.DeserializeObject(jsonText, settings);
var dateTime = jsonObject["LastModified"]["DateTime"];
It also works with dates like "932 AD, a little before lunch time".

How do you set the DateTime format string in Newtonsoft?

I'm trying to get Newtonsoft to convert a string to a DateTime. This is the string:
13/02/2019 05:13
I try to tell Newtonsoft how to do this by using one of these:
var dateTimeConverter = new IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy HH:mm" };
var converters = new List<JsonConverter>() { dateTimeConverter };
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = converters
};
or
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
DateFormatString = "dd'/'MM'/'yyyy' 'HH':'mm"
};
and of course it will just go right ahead and tell me that's fine and then blow up as it tries to process the second day of the thirteenth month.
I need this to work globally. How do I get Newtonsoft to do this?
This was in WebAPI and the problem was I wasn't setting the same Json.Net that WebAPI was using.
I fixed it by putting this in Application_Start of global.asax.cs:
var dateTimeConverter = new IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy HH:mm" };
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(dateTimeConverter);
you can convert a string to a datetime like this :
string iString = "2005-05-05 22:12 PM";
DateTime oDate = DateTime.ParseExact(iString, "yyyy-MM-dd HH:mm tt",null);
MessageBox.Show(oDate.ToString());
i hope to help you.. :/

Read date from JObject JSON.Net

I want to dynamically read json. I have everything working but date. So I have
JObject obj = JObject.Load(reader);
data.location= (obj["duration"].Value<double>());
data.deviceID = (obj["deviceID"].Value<string>());
data.reason= (obj["reason"].Value<string>());
data.id= (obj["id"].Value<string>());
// data.startTime=(obj["startTime"].Value<DateTime>());
string start = (string)obj.SelectToken("startTime");
In quickwatch the date looks like
so I tried date time with no luck. If i can get the string value I found a different stackoverflow post that used this for a solution. However I can not read it in a good manner yet
private DateTime TryParseIso8601(string s)
{
string format = s.EndsWith("Z") ? "yyyy-MM-ddTHH:mm:ssZ" : "yyyy-MM-ddTHH:mm:sszzz";
DateTime date = new DateTime();
DateTime.TryParseExact(s, format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out date);
return date;
}
Per comment, the exception generate by
data.startTime = (obj["startTime"].Value<DateTime>());
is
You can use the SelectToken to read the date.
var jToken = obj.SelectToken("startTime.$date");
var date = jToken.Value<DateTime>();
Check this live fiddle - https://dotnetfiddle.net/9o4FJt
Sample Code:
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
var jsonString = "{\"startTime\" : { \"$date\" : \"2018-03-19T19:38:02.929Z\"} }";
var jObj = JsonConvert.DeserializeObject<JObject>(jsonString);
Console.WriteLine(jObj);
var jToken = jObj.SelectToken("startTime.$date");
Console.WriteLine(jToken.Value<DateTime>());
Console.WriteLine("Hello World");
}
}

Parsing a JSON date info into a C# DateTime

I have a a WCF service that returns a CLR object. This object is defined as follows:
[DataContract]
public class Person
{
[DataMember]
public string FullName
{
get { return fullName; }
set { id = fullName; }
}
private string fullName = string.Empty;
[DataMember]
public DateTime BirthDate
{
get { return birthDate; }
set { birthDate = value; }
}
}
Instances of this object are being created and returned from my WCF service. This service looks like the following:
[OperationContract]
[WebGet(UriTemplate = "/GetPersonByID/{id}", ResponseFormat = WebMessageFormat.Json)]
public Person GetPersonByID(string id)
{
Person person = FindPersonByID(id);
return person;
}
When I get the response back in my application, I can successfully extract the FullName value. However, I haven't successfully been able to convert the BirthDate to a C# DateTime object in my client application. When converted to a string, the BirthDate looks something like this:
\/Date(1297367252340-0500)\/
How do I get that into a C# DateTime instance?
Thanks!
Here are two options:
You can use the Deserialize method from System.Web.Script.Serialization.JavaScriptSerializer (in System.Web.Extensions.dll).
or you could use the ReadObject method from System.Runtime.Serialization.Json.DataContractJsonSerializer (in System.Runtime.Serialization.dll or in .NET 3.5 in System.ServiceModel.Web.dll).
Make sure that your date is wrapped in quotes like:
string dateString = #"""\/Date(1297367252340-0500)\/""";
The reason the date is in this weird format is that DateTime is a primitive in WCF. Unfortunately, there is no universally standardized format for serializing dates and times in JSON -- various frameworks use various string formats.
The dilemma is that WCF needs to natively understand that a particular string over the wire is indeed a DateTime, not just another plain vanilla JSON string. Hence the strange format. As soon as DataContractJsonSerializer encounters a date starting with \/Date, it starts trying to parse it as a date.
Now, to answer your question, when you are sending a DateTime over the wire, it depends on if you're using a web browser client, a Silverlight client, or a WCF client.
A WCF client or a Silverlight 2+ client should NOT have problems with this -- they should auto-use the DataContractJsoNSerializer, and if they're not using it, you can plug in DCJS manually.
If you are using a web client, you can include the .js file that ships with ASP. NET AJAX (I believe it is called MicrosoftAspNetAjax.js, or MicrosoftAjax.cs, though the name may have changed). Its deserialize function will auto-parse these dates as well.
Hope that helps!
Well, lately I had to work on an Android Mobile (Xamarin Studio) app project where I was unable to use Newtonsoft Json (Json.NET) due to errors thrown during deployment to this specific device version (Android API 16 Version 4.2.1).
Luckly I found an alternative library for json (System.Json). However this library does not have a way of casting JSON date to C# DateTime implicitly.
I have created the following two functions for nullable date and date conversions from a string json date(i.e /Date(1389435240000+0000)/)
The code can be improved but it does the job for now
public static DateTime? ConvertToNallableDate(string date)
{
DateTime? val = null;
/* /Date(1389435240000+0000)/*/
try{
if(!string.IsNullOrEmpty(date))
{
date = date.Replace ("/Date(", string.Empty).Replace (")/", string.Empty);
int pIndex = date.IndexOf ("+");
if(pIndex < 0) pIndex = date.IndexOf("-");
long millisec = 0;
date = date.Remove (pIndex);
long.TryParse (date, out millisec);
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-GB");
DateTime newDate = DateTime.Parse ("1970,1,1", ci);
newDate = newDate.AddMilliseconds(millisec);
val = newDate == null ? (DateTime?)null : newDate;
}
}catch {
val = null;
}
return val;
}
public static DateTime ConvertToDate(string date)
{
DateTime val = new DateTime();
/*/Date(1389435240000+0000)/*/
try{
if(!string.IsNullOrEmpty(date))
{
date = date.Replace ("/Date(", string.Empty).Replace (")/", string.Empty);
int pIndex = date.IndexOf ("+");
if(pIndex < 0) pIndex = date.IndexOf("-");
long millisec = 0;
date = date.Remove (pIndex);
long.TryParse (date, out millisec);
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-GB");
DateTime newDate = DateTime.Parse ("1970,1,1", ci);
val = newDate.AddMilliseconds(millisec);
}
}catch {
val = new DateTime();
}
return val;
}
This solved my problem
using System.Web.Script.Serialization;
//code
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
DateTime ddate = json_serializer.Deserialize<DateTime>(#"""\/Date(1326038400000)\/""").ToLocalTime();

String date time format

I am using the Vimeo API and I want to convert the string <upload_date> to a short date format, {0:d} or {0:dd/mm/yyyy}.
This is my code but it doesn't seem to be working for me.
select new VimeoVideo
{
Date = String.Format("{0:d}",(item.Element("upload_date").Value)),
};
return Vids.ToList();
}
public class VimeoVideo
{
public string Date { get; set; }
}
As Oleg suggested you can try to parse your value to DateTime and then format it (use try catch if needed). That should work (not 100% sure since I don't know what item's type is).
var myDate = DateTime.Parse(item.Element("upload_date").Value);
Date = String.Format("{0:d}", myDate);
http://msdn.microsoft.com/it-it/library/1k1skd40(v=VS.80).aspx
Just verify the type of the Value property.. The above string formatter works for System.DateTime structure.. I assume in your case its string type object. According to the given sample date time string i have written this code.. Try out this.
CultureInfo provider = CultureInfo.InvariantCulture;
var format = "yyyy-MM-dd HH:mm:ss";
var dt = DateTime.ParseExact(item.Element("upload_date").Value, format, provider);
Date = string.Format("{0:d}", dt);
Hope it works..

Categories

Resources