JSON.NET Exception when deserializing a DateTime value - json

I reflected the JSON.NET JavaScriptDateTimeConverter class code, copied it, and renamed the class AS3DateTimeConverter so that I could modify it to format DateTime objects in a more precise and strongly-typed manor.
I have it output a type according to how JSON.NET outputs strongly-typed objects like so:
{"$type":"System.DateTime, mscorlib","ticks":0}
The overridden WriteJson method of the JsonConverter runs to produce that value.
However, when I try to deserialize the string using the exact same settings with the same converter, the overridden ReadJson method never gets a chance to run and construct a DateTime from the ticks property, because the following errors occurs:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.DateTime' because the type requires a JSON primitive
value (e.g. string, number, boolean, null) to deserialize correctly.
To fix this error either change the JSON to a JSON primitive value
(e.g. string, number, boolean, null) or change the deserialized type
so that it is a normal .NET type (e.g. not a primitive type like
integer, not a collection type like an array or List) that can be
deserialized from a JSON object. JsonObjectAttribute can also be added
to the type to force it to deserialize from a JSON object.
Path 'ticks', line 1, position 45.
Is this some kind of bug or limitation, which will not allow me to revive a DateTime type because it is a value-type? Or am I missing something?
Here are the serialization settings:
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.PreserveReferencesHandling = PreserveReferencesHandling.All;
settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
settings.ConstructorHandling = ConstructorHandling.Default;
settings.TypeNameHandling = TypeNameHandling.All;
settings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime;
settings.Converters.Add( new AS3DateTimeConverter() );
//settings.Binder = new AS3SerializationBinder();
string s = JsonConvert.SerializeObject( new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc ), settings );
object o = JsonConvert.DeserializeObject( s, settings ); //s = "{\"$type\":\"System.DateTime, mscorlib\",\"ticks\":0}" //ERROR OCCURS HERE

The problem seems to have something to do with deserializing a bare date. When the Date is wrapped in another object, it seems to work. This code works for me:
public class Program
{
public static void Main(string[] args)
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.PreserveReferencesHandling = PreserveReferencesHandling.All;
settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
settings.ConstructorHandling = ConstructorHandling.Default;
settings.TypeNameHandling = TypeNameHandling.All;
settings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime;
settings.Converters.Add(new AS3DateTimeConverter());
TestObject obj = new TestObject { Date = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) };
string s = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine(s);
object o = JsonConvert.DeserializeObject(s, settings);
Console.WriteLine(((TestObject)o).Date.ToString());
}
}
public class TestObject
{
public DateTime Date { get; set; }
}
public class AS3DateTimeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject jo = new JObject();
jo.Add("$type", "System.DateTime, mscorlib");
jo.Add("ticks", ((DateTime)value).Ticks);
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
return new DateTime(jo["ticks"].Value<long>());
}
}
Output:
{"$id":"1","$type":"Q20224027.TestObject, JsonTest","Date":{"$type":"System.DateTime, mscorlib","ticks":621355968000000000}}
1/1/1970 12:00:00 AM
UPDATE
To test the theory of whether converters get called for custom top level objects with embedded type information, I made a converter for the date wrapper object and serialized that instead. This worked, but only if I gave it a hint by using DeserializeObject<T> instead of DeserializeObject. Here is the code:
namespace Q20224027
{
public class Program
{
public static void Main(string[] args)
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.PreserveReferencesHandling = PreserveReferencesHandling.All;
settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
settings.ConstructorHandling = ConstructorHandling.Default;
settings.TypeNameHandling = TypeNameHandling.All;
settings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime;
settings.Converters.Add(new DateWrapperConverter());
DateWrapper obj = new DateWrapper { Date = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) };
string s = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine(s);
object o = JsonConvert.DeserializeObject<DateWrapper>(s, settings);
Console.WriteLine(((DateWrapper)o).Date.ToString());
}
}
public class DateWrapper
{
public DateTime Date { get; set; }
}
public class DateWrapperConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateWrapper);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
DateWrapper obj = (DateWrapper)value;
JObject jo = new JObject();
jo.Add("$type", typeof(DateWrapper).AssemblyQualifiedName);
jo.Add("ticks", obj.Date.Ticks);
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
return new DateWrapper { Date = new DateTime(jo["ticks"].Value<long>()) };
}
}
}
Output:
{"$type":"Q20224027.DateWrapper, JsonTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","ticks":621355968000000000}
1/1/1970 12:00:00 AM

Workaround I found.
If the object is wrapped in a list before being serialized, then it works ok, but only if you decorate the class with a JsonConverter attribute specifying the converter. Adding the converter to the list of converters for the serializers settings is insufficient.
For example, if you have a "Node" class which has a "Child" Node member (i.e. the type has members of it's own type), and you nest some nodes, then what I've found is that the converter is not called during serialization for anything but the top node when you only add the converter to the list of converters. On the other hand, if you explicitly decorate the class with the converter, then all the child nodes are run through the converter's WriteJson method as expected. So this basically renders the "Converters" collection of the serializer's settings non-functional.
When the objects are members of an array and their type is decorated with an explicit converter, then their converter's ReadJson and WriteJson methods are called when the types are encountered during serialization and deserialization.
When receiving a JSON string from a client, there are only two options to get it to work. Either you manually wrap the string in an object including a generic List "$type" and embed the received value as the sole value in the "$values" array, or you must just avoid all this and hard-code the expected recieved object type by calling typed DeserializeObject<T> method. What a mess.
The only reason I can fathom any of this making sense is if the DeserializeObject (non-generic) method was explicitly intended to NOT call converters for the top-level object, presumably so that it could be used in custom converter's WriteJson method without causing recursive calls to the converter. If that's the case, the design is terrible, because it leads to all the problems I've discussed.

Related

How to validate JSON using System.Text.Json before deserialization

In .NET Core 5.0, using System.Text.Json.JsonSerializer Deserialize(someJsonFile) i get:
System.Text.Json.JsonException: 'The JSON value could not be converted to System.Guid. Path: $.someGuid | ..
which is expected, since the the someGuid property is of type System.Guid and the value of someGuid in the JSON file/string is:
{
"someGuid": ""
}
which can not be deserialized properly .. (since it's not Guid.Empty)..
To my question.
What's a good and generic implementation to validate the Json before deserializing it (in general)? like TryParse or JsonDocument.Parse? sure, try-catch but that's dirty (imho).
btw: i don't want to use Newtonsoft
thanks for your suggestions (and critics of course).
I created a custom converter using the example is this answer: The JSON value could not be converted to System.Int32
public class StringToGuidConverter : JsonConverter<Guid>
{
public override Guid Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
ReadOnlySpan<byte> span = reader.ValueSpan;
if (Utf8Parser.TryParse(span, out Guid guid, out int bytesConsumed) && span.Length == bytesConsumed)
{
return guid;
}
if (Guid.TryParse(reader.GetString(), out guid))
{
return guid;
}
}
return Guid.Empty;
}
public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
In my case my model to deserialize to can't take Nullable Guid so I return an empty GUID and then validate this in my logic.
Because I'm create a web api using .Net standard, I can't register this in the services at the startup class. But you can register the custom converter using the JsonSerializerOptions property when calling the Deserialize method like this:
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
Converters = { new NERDS.API.Helpers.StringToGuidConverter() }
};
StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream);
string json = reader.ReadToEnd();
return JsonSerializer.Deserialize<T>(json, options);

JsonConstructorAttribute in System.Text.Json (but not Newtonsoft.Json) results in exception when property and constructor argument types differ

Given a Base64 string, the following sample class will deserialize properly using Newtonsoft.Json, but not with System.Text.Json:
using System;
using System.Text.Json.Serialization;
public class AvatarImage{
public Byte[] Data { get; set; } = null;
public AvatarImage() {
}
[JsonConstructor]
public AvatarImage(String Data) {
//Remove Base64 header info, leaving only the data block and convert it to a Byte array
this.Data = Convert.FromBase64String(Data.Remove(0, Data.IndexOf(',') + 1));
}
}
With System.Text.Json, the following exception is thrown:
must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive.
Apparently System.Text.Json doesn't like the fact the property is a Byte[] but the parameter is a String, which shouldn't really matter because the whole point is that the constructor should be taking care of the assignments.
Is there any way to get this working with System.Text.Json?
In my particular case Base64 images are being sent to a WebAPI controller, but the final object only needs the Byte[]. In Newtonsoft this was a quick and clean solution.
This is apparently a known restriction of System.Text.Json. See the issues:
[JsonSerializer] Relax restrictions on ctor param type to immutable property type matching where reasonable #44428 which is currently labeled with the 6.0.0 Future milestone.
System.Text.Json incorrectly requires construct parameter types to match immutable property types. #47422
JsonConstrutor different behavior between Newtonsoft.Json and System.Text.Json #46480.
Thus (in .Net 5 at least) you will need to refactor your class to avoid the limitation.
One solution would be to add a surrogate Base64 encoded string property:
public class AvatarImage
{
[JsonIgnore]
public Byte[] Data { get; set; } = null;
[JsonInclude]
[JsonPropertyName("Data")]
public string Base64Data
{
private get => Data == null ? null : Convert.ToBase64String(Data);
set
{
var index = value.IndexOf(',');
this.Data = Convert.FromBase64String(index < 0 ? value : value.Remove(0, index + 1));
}
}
}
Note that, ordinarily, JsonSerializer will only serialize public properties. However, if you mark a property with [JsonInclude] then either the setter or the getter -- but not both -- can be nonpublic. (I have no idea why Microsoft doesn't allow both to be private, the data contract serializers certainly support private members marked with [DataMember].) In this case I chose to make the getter private to reduce the chance the surrogate property is serialized by some other serializer or displayed via some property browser.
Demo fiddle #1 here.
Alternatively, you could introduce a custom JsonConverter<T> for AvatarImage
[JsonConverter(typeof(AvatarConverter))]
public class AvatarImage
{
public Byte[] Data { get; set; } = null;
}
class AvatarConverter : JsonConverter<AvatarImage>
{
class AvatarDTO { public string Data { get; set; } }
public override AvatarImage Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dto = JsonSerializer.Deserialize<AvatarDTO>(ref reader, options);
var index = dto.Data?.IndexOf(',') ?? -1;
return new AvatarImage { Data = dto.Data == null ? null : Convert.FromBase64String(index < 0 ? dto.Data : dto.Data.Remove(0, index + 1)) };
}
public override void Write(Utf8JsonWriter writer, AvatarImage value, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, new { Data = value.Data }, options);
}
This seems to be the easier solution if for simple models, but can become a nuisance for complex models or models to which properties are frequently added.
Demo fiddle #2 here.
Finally, it seems a bit unfortunate that the Data property will have some extra header prepended during deserialization that is not present during serialization. Rather than fixing this during deserialization, consider modifying your architecture to avoid mangling the Data string in the first place.
Implementing the custom converter deserialization using an ExpandoObject can avoid the nested DTO class if desired:
using System.Dynamic;
.
.
.
public override FileEntity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
dynamic obj = JsonSerializer.Deserialize<ExpandoObject>(ref reader, options);
return new FileEntity {
Data = (obj.data == null) ? null : Convert.FromBase64String(obj.data.GetString().Remove(0, obj.data.GetString().IndexOf(',') + 1))
};
}
it makes the custom converter a little more flexible when developing, since the DTO doesn't continually need to grow with the base class being deserialized into. It also makes handling potential nullable properties a bit easier too (over standard JsonElement deserialization, i.e. JsonSerializer.Deserialize< JsonElement >) as such:
public override FileEntity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
dynamic obj = JsonSerializer.Deserialize<ExpandoObject>(ref reader, options);
return new FileEntity {
SomeNullableInt32Property = obj.id?.GetInt32(),
Data = (obj.data?.GetString() == null) ? null : Convert.FromBase64String(obj.data.GetString().Remove(0, obj.data.GetString().IndexOf(',') + 1))
};
}

JSON Deserialization of Cast object returns Uncast JSON

I'm currently doing some work on an API where I'm Casting an object before serializing it and returning the JSON. I expected the JSON result to be that of the Cast object and not the Uncast object, however I get all the properties in my JSON from the Uncast object
Example code
using System;
using Newtonsoft.Json;
namespace JSONSerializationOfCastObject
{
class Program
{
static void Main(string[] args)
{
B InstanceB = new B(){PropA = "A",PropB = "B"};
A InstanceA = InstanceB;
var JSONInstanceA = JsonConvert.SerializeObject(InstanceA);
Console.WriteLine(JSONInstanceA);
Console.ReadLine();
}
}
public class A
{
public string PropA { get; set; }
}
public class B:A
{
public string PropB { get; set; }
}
}
Result
{"PropB":"B","PropA":"A"}
Expected result
{"PropA":"A"}
Another example where the type just isn't what you expect
B InstanceB = new B(){PropA = "A",PropB = "B"};
A InstanceA = InstanceB;
var x = InstanceA.GetType() == typeof(A); //==> False but we casted it to A
I just cannot figure this out, NewtonSoft must do some reflection under the hood.
GitHub Example here: https://github.com/tharris29/JSONSerializationOfCastObject/tree/master
update
So I understand this is to do with reflection but just seems an odd result. Is there a way to tell the serializer what object type to use for serialization?
Just because you have assigned a B to an A does not mean that it is no longer a B. You can see this for yourself if you print out the type of your InstanceA variable after the assignment:
B instanceB = new B() { PropA = "A", PropB = "B" };
A instanceA = instanceB;
Console.WriteLine(instanceA.GetType().Name);
As you will see, the result is B.
Json.Net uses reflection to look at the actual type of an object and get all of its properties. As far as I know, it does not have a built-in way to limit the properties to just those of a base type. If you want to do that, you will need a custom JsonConverter. Here is one that might work for you (notice it also uses reflection):
public class BaseTypeConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
T instance = (T)value;
JObject obj = new JObject();
foreach (PropertyInfo prop in typeof(T).GetProperties())
{
if (prop.CanRead)
{
obj.Add(prop.Name, JToken.FromObject(prop.GetValue(instance)));
}
}
obj.WriteTo(writer);
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
You can use this converter like this:
B instanceB = new B() { PropA = "A", PropB = "B" };
// serialize B, but only include the properties from type A
string json = JsonConvert.SerializeObject(instanceB, new BaseTypeConverter<A>());
Console.WriteLine(json);
Output:
{"PropA":"A"}

Webapi with entity framework - use customer JSON converter to serialized DbGeography not working

I am using webapi with DbGeography spatial data and want to serialize to json.
By default, DbGeography serializes to null. So I implemented my own converter for it.
Here is what I have so far, but it doesn't seem to work.
Basically, with the following code, my DbGeographyConverter.WriteJson method is never under debug and the Location property is serialized as null
Customer converter:
public class DbGeographyConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
DbGeography contextObj = value as DbGeography;
writer.WriteStartObject();
writer.WritePropertyName("Lat");
serializer.Serialize(writer, contextObj.Latitude);
writer.WritePropertyName("Long");
serializer.Serialize(writer, contextObj.Longitude);
writer.WriteEndObject();
}
public override bool CanConvert(Type objectType)
{
if (objectType == typeof(DbGeography))
{
return true;
}
return false;
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
Add convert in Global.ascx.cs
protected void Application_Start()
{
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
new DbGeographyConverter()
}
Finally, apply converter to the data model class property
public DataModelClass1
{
[JsonConverter (typeof(DbGeographyConverter))]
public DbGeography Location { get; set; }
}
First, since you're adding your custom converter to the SerializerSettings.Converters collection, you don't need to decorate your DataModelClass1's Location property with the JsonConverterAttribute- The JsonFormatter will run through the aforementioned collection until it finds the derived JsonConverter you added without the attribute.
Now back to your question- which browser are you testing this in and how? If I were to speculate, I'd say you're using either Chrome or Firefox with GET requests, both of which prioritize application/xml over application/json in the accept header they send to the server. For that reason Web API will see that the browsers prefer XML over JSON and the JsonFormatter will never be touched, let alone your custom JsonConverter.
There are a few workarounds to this. On the browser side the easiest way is to make ajax GET requests with jQuery and specify that you want JSON back. On the server side, you can remove application/xml from the SupportedMediaTypes.
I spent quite awhile on this. You'd only use the write method if you wanted to change the default output format of the Json for DbGeography from this
"geography": {
"coordinateSystemId": 4326,
"wellKnownText": "POINT (77.6599502563474 12.9602302518557)"
}
to something else like "77.22, 12.8" - just a single string.
If you're looking to convert a string like that to DbGeography on reading Json from the request, the code below is what you're after
public class DbGeographyConverter : JsonConverter
{
public override bool CanConvert ( Type objectType )
{
return objectType.IsAssignableFrom( typeof( string ) );
}
public override object ReadJson ( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
{
if ( reader.Value == null ) {
return null;
}
return Parser.ToDbGeography( reader.Value.ToString() );
}
public override void WriteJson ( JsonWriter writer, object value, JsonSerializer serializer )
{
// Base serialization is fine
serializer.Serialize( writer, value );
}
}
This is the code for the Converter if you're passing in a string value - 12,99
Which will be you're lat and lng
This sample application has the answer you're looking for.
https://code.msdn.microsoft.com/windowsazure/HTML-ASPNET-Web-API-Bing-58c97f9f
The Converter code from this can be found here
https://github.com/Azure-Samples/SQLDatabase-Spatial-WebAPI-BingMaps/blob/master/SpatialTypesWithWebAPI/Models/DbGeographyConverter.cs

Parsing JSON DateTime from Newtonsoft's JSON Serializer

I've serialized an object using Newtonsoft's JSON serializer, and the DateTime has come through as:
/Date(1237588418563+0000)/
When I $.evalJSON() on that, it is an object but I can't find any normal Date methods like toUTCString on it.
Any ideas what I can do with this?
Use one of the JsonConverters that come with Json.NET for working with dates to get a better format. JavaScriptDateTimeConverter will automatically give you a JavaScript date.
public class LogEntry
{
public string Details { get; set; }
public DateTime LogDate { get; set; }
}
[Test]
public void WriteJsonDates()
{
LogEntry entry = new LogEntry
{
LogDate = new DateTime(2009, 2, 15, 0, 0, 0, DateTimeKind.Utc),
Details = "Application started."
};
string defaultJson = JsonConvert.SerializeObject(entry);
// {"Details":"Application started.","LogDate":"\/Date(1234656000000)\/"}
string javascriptJson = JsonConvert.SerializeObject(entry, new JavaScriptDateTimeConverter());
// {"Details":"Application started.","LogDate":new Date(1234656000000)}
string isoJson = JsonConvert.SerializeObject(entry, new IsoDateTimeConverter());
// {"Details":"Application started.","LogDate":"2009-02-15T00:00:00Z"}
}
Documentation: Serializing Dates in JSON with Json.NET
I came up with a different approach which might be useful to some. Basically I create my own CustomDateConverter that I call when I need it. The converter takes 2 parameters, a date format e.g. yyyy-MM-dd HH:mm:ss and a TimeZoneInfo, which allows me to convert the date from UTC to the user's time zone:
public class JSONCustomDateConverter : DateTimeConverterBase
{
private TimeZoneInfo _timeZoneInfo;
private string _dateFormat;
public JSONCustomDateConverter(string dateFormat, TimeZoneInfo timeZoneInfo)
{
_dateFormat = dateFormat;
_timeZoneInfo = timeZoneInfo;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(TimeZoneInfo.ConvertTimeFromUtc(Convert.ToDateTime(value), _timeZoneInfo).ToString(_dateFormat));
writer.Flush();
}
You can use it like this:
var jsonString = JsonConvert.SerializeObject(myObject, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Converters = new List<JsonConverter>() { new JSONCustomDateConverter("yyyy-MM-dd HH:mm:ss", loggedUser.Timezone) } });
Obviously you could remove anything related to time zone if you only want custom date formatting. Let me know it that helped!
As of Newtonsoft Json.Net version 4.5r5 you use the JsonPropertyAttribute Class class and set its ItemConverterType Property property.
Usage:
// class to be serialized
public class MyClass
{
[JsonProperty(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
public DateTime? DateTime1;
public DateTime? DateTime2;
}
As I have observed this will set the DateTimeConverter for all properties in this class not just the one before which is declared.
Ran into the same problem, and found a solution based on the link from Adam:
new Date(yourDate.substr(yourDate.indexOf("(") + 1, 13) - 0));
It looks like a Unix timestamp, which javascript is easily able to convert into a date object. The - 0 is simply to make javascript treat the substr output as an integer... I guess you could Number() it as well, if you don't like the looks of - 0
The JSON object contained something like this:
var data = {"CreatedDate":"/Date(1327572000000-1000)/"});
///
var oddDateTimeZone = data.CreatedDate;
var utcDateTime = oddDateTimeZone.substr(oddDateTimeZone.indexOf("(")+1, 13);
var utcZone = oddDateTimeZone.substr(oddDateTimeZone.indexOf("-")+1, 4);
var utcDateTimeZone = new Date(Number(utcDateTime)-(Number(utcZone)));
but, still it would be better to fix the JSON object so the date function fired without using something like eval() or window[]. Maybe in jQuery. Not sure.
Don't forget that the offset could be + and not just - for the offset!
Sorry I simplify a bit #James Newton-King
string date = Newtonsoft.Json.JsonConvert.SerializeObject(DateTime.Now);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
This works for me