API response Include milliseconds when serializing DateTime even if component is zero - c#

DateTimeStamp : 2022-04-29 15:19:41.350 after serialization 2022-04-29T22:19:41.35Z instead of 2022-04-29T22:19:41.350Z
I have fixed this using below code :
public static void ServiceJsonSettings(HttpConfiguration config, IServiceMetadata serviceMetadata)
{
config.Formatters.Insert(0, new JsonNewtonsoftJilFallbackFormatter());
IsoDateTimeConverter dateConverter = new IsoDateTimeConverter
{
DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fff'Z'",
DateTimeStyles = DateTimeStyles.AdjustToUniversal
};
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(dateConverter);
}
Now for large object serialization i am using Jil Serializer configured as below:
public static readonly Options JilOptions = new Options(excludeNulls: true, includeInherited: true,
serializationNameFormat: SerializationNameFormat.CamelCase, dateFormat: DateTimeFormat.ISO8601);
Using both Serializer Newtonsoft and JIL the output I am getting expected result : 2022-04-29T22:19:41.350Z.
But after testing it i found JIL serializer Serializer is trimming the zeros in millisecond part if it ends with 00 for ex: DateTimeStamp : 2022-04-29 15:19:41.300 serialized to 2022-04-29T22:19:41.3Z. On the other hand newtonsoft serializer produce expected result 2022-04-29T22:19:41.300Z.
Is there any way to provide dateFormat as "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fff'Z'" in JilOptions ?

Related

Cannot deserialize JSON with both UTC and non UTC formatted datetimes

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

How to correctly deserialize a Json DateTimeOffset?

i got a problem while i try to deserialize a DateTimeOffset from a json. I saw a lot of questions here, but no one seems to work. I got from Json this dateTime : 05/04/2019 02:39:33 PM GMT and i want to keep the offset to zero. After the deserialization, by the way, i got my object with same exact time(In this case 02:39:33 PM) but with my time zone ( +02:00). I tried these two workaround, without success:
First of all, i tried to setup setting to my deserializer:
JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
DateParseHandling = DateParseHandling.DateTimeOffset,
DateFormatString = "dd/MM/yyyy hh:mm:ss tt 'GMT'"
};
I tried this converter too:
class DateFormatConverter : IsoDateTimeConverter
{
public DateFormatConverter(string format)
{
DateTimeFormat = format;
DateTimeStyles = System.Globalization.DateTimeStyles.AssumeUniversal;
}
So, i expected this reseult:
05/04/2019 02:39:33 PM +00:00
thanks to all that will answer me!
Maybe change DateParseHandling.DateTimeOffset to DateParseHandling.None?
I managed to got the expected result by change DateParseHandling = DateParseHandling.None in the Setting of serializer.

json.net and wrong dates with +00:00 suffix

I serialize objects having DateTime properties, like this: JsonConvert.SerializeObject(my_object), then on another machine I deserialize: result = JsonConvert.DeserializeObject<Result>(r);. And some dates are wrong. I've checked through fiddler that when date in json looks like this Date=2014-11-29T18:41:41.1672899 then it's deserialized correctly, but every 10th or so entry looks like Date=2014-11-29T18:55:39.1175417+00:00 (note the +00:00) and then it's deserialized as date shifted by two hours. Why is this and how to fix this?
You can explicitly set DateTimeZoneHandling to DateTimeZoneHandling.Utc on JsonSerializerSettings:
Result result = JsonConvert.DeserializeObject<Result>(r, new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc
});

Json.Net cannot deserialize DateTime.MinValue

I've tried deserializing a Json string containing DateTime.MinValue in every conceivable way, but when the set method gets called on my object. The date always gets changed from -01-01-01- to -01-01-02-.
The Json being parsed clearly contains
"inception_date": "0001-01-01T00:00:00+00:00"
I then call JsonConvert on it:
return JsonConvert.DeserializeObject<T>(json, deserializerSettings);
Where T is a basic struct that contains a property: DateTime inception_date { get; set; } property. The deserializer settings are as follows:
deserializerSettings = new JsonSerializerSettings()
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc
};
Yet somewhere in the bowels of Newtonsoft.Json.dll, the above time gets converted to the following jObject.
"inception_date": "0001-01-02T00:00:00Z"
I have no way of stepping into their code, but by the damage is done before my code sees another call. ReadJson in the JsonConverter calls serializer.Populate(jObject.CreateReader(), target); where target is an instance of my class T, and jObject has somehow been rendered with the above incorrect date.
Can anyone figure out why this is happening or how I can prevent it? The jObject seems to be getting created in a way that is ignoring my serializer settings, which explicitly say not to screw with the date string (DateParseHandling.None).
I've taken screen shots to illustrate exactly where Newtonsoft's JsonConvert method seems to have lost a vital configuration value.
As you can see, this is the point in the code where I call JsonConvert:
The dateParseHandling value is set to None, and that's how it should be for this to work.
At this next step, I've jumped a few internal Newtonsoft calls and landed in a generic implementation of the JsonConverter which I borrowed from an accepted reference implementation to be able to see what was going on. The JsonReader passed in suddenly has lost that dateParseHandling value:
Because of this value being switched back to DateTime - the internal workings of the jObject try to represent this as an internal localized DateTime, which underflows because my timezone is negative, and we're already representing the minimum DateTime value, resulting in the conversion back to UTC adding a full day.
Try:
deserializerSettings = new JsonSerializerSettings()
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset
}
This resulted in me getting 1/1/0001 12:00:00 AM instead of 1/2/0001 12:00:00 AM
Here is my test code (written in LINQPad)
void Main()
{
var deserializerSettings = new JsonSerializerSettings()
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc
};
var json = "{\"inception_date\": \"0001-01-01T00:00:00+00:00\"}";
var parsedObj = JsonConvert.DeserializeObject<TestClass>(json, deserializerSettings);
Console.WriteLine(parsedObj);
deserializerSettings = new JsonSerializerSettings()
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset
};
parsedObj = JsonConvert.DeserializeObject<TestClass>(json, deserializerSettings);
Console.WriteLine(parsedObj);
}
public class TestClass
{
public DateTime inception_date {get;set;}
}
Outputs:

JSON Serialization in Web Api 2 not using ISO 8601 dates

I'm using WebApi 2 to send some Json down to the client and its using the old style Date serialization and not ISO 8601.
I'm seeing:
"current_period_start": "\/Date(1388153705)\/",
"current_period_end": "\/Date(1390832105)\/",
"start": "\/Date(1388332525)\/",
My Global.asax.cs looks like this:
GlobalConfiguration.Configure(WebApiConfig.Register);
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Converters.Add(new IsoDateTimeConverter());
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
Newtonsoft.Json defaults to IsoDateTimeConverter. So even if you do not specify anything, you should get the correct Iso format (and for me your code also works just fine btw.).
Read this or Scott's blog for further info about the defaults
You are most likely setting the converter somewhere else again, maybe you are using some custom converter with specific settings? Or are you using a very old version of Newtonsoft.Json?
Just a quick comment on #Toolkit's comment about the formatting.
The reason why you get a date string without the Z at the end is the datetime variable that you are parsing have the Kind as Unspecified.
It is likely that you are parsing a record coming from a database with a DateTime property, the database field lose the Kind once is saved.
This is why json is not adding the 'Z' at the end, it doesn't know if it is utc or local.
You can use a DatetimeOffset instead of Datetime, if you can change the model without too much impact. My option was to write a custom parser for Datetime and force it to be UTC if was not specified.
public class CustomJsonDateConverter : DateTimeConverterBase
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var date = DateTime.Parse(reader.Value.ToString());
if (date.Kind == DateTimeKind.Unspecified)
{
date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
}
return date;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var date = (DateTime)value;
if (date.Kind == DateTimeKind.Unspecified)
{
date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
}
writer.WriteValue(date);
}
}
PD: I don't have enough points to write a comment, this isn't an answer to the main issue.

Categories

Resources