JSON.NET Serialize Date - c#

I would like to serialize my date to be in a specific format but I can't get my act together.
I tried building a nice little class but the output gets wrapped in quotes, which doesn't work.
I'd like the JSON to look like this...
{
date : new Date(2013, 8, 30)
}
but I get this...
{
date: "new Date(2013, 8, 30)"
}
my class
public class DateCell : ChartCell
{
[JsonIgnore]
public DateTime Value { get; set; }
[JsonProperty(PropertyName = "date")]
public override object DataValue
{
get
{
return string.Format("new Date({0}, {1}, {2})", this.Value.Year, this.Value.Month - 1, this.Value.Day);
}
}
}

There's a difference between a JavaScript Object and JSON. What you described might be valid in a JavaScript object, but it is not valid JSON. JSON does not allow the representation that you are asking for.
In JSON a value can only be one of the following:
A string, such as "abc"
A number, such as 123 or -12.34
A literal value of true, false, or null
An array of other valid values, such as [1,"a",true]
Another JSON object, such as { a: 1, b: "abc" }
It cannot just be a JavaScript Object, or any other arbitrary JavaScript. See the spec at json.org.
Passing a Date object constructor would not make any sense, as JSON is a general purposed serialization format, and Date is a JavaScript native class. How would you expect non-JavaScript code to interpret this?
While there is no specific date or time format defined by the JSON standard, the de facto standard is the ISO 8601 format. Your DateTime would look something like "2013-09-30T00:00:00". There are other ways to serialize a date, but they are not as uniform or popular.
In JSON.Net, the ISO 8601 format is the default. So you don't need to do anything special other than just to serialize your object with its original properties.
public class DateCell : ChartCell
{
public DateTime Value { get; set; }
}
UPDATE
Since you said in comments that you are passing this to Google Charts, it appears from their reference that they are using a nonstandard format that looks like the Date constructor, but has omitted the new keyword. Why they do this, I'm not sure, but you should be able to modify your original code as follows:
public class DateCell : ChartCell
{
[JsonIgnore]
public DateTime Value { get; set; }
[JsonProperty(PropertyName = "date")]
public override object DataValue
{
get
{
return string.Format("Date({0},{1},{2})", this.Value.Year, this.Value.Month - 1, this.Value.Day);
}
}
}

Related

Parse custom JSON string to DateTime Convert in API

My Question is similar to this one (The JSON value could not be converted to System.DateTime), where I am trying to convert an input string to an DateTime. The difference, however, is that the input string cannot be changed. I have no choice in it.
[HttpPut("PutBodyToFoodChain")]
public async Task<IActionResult> PutBodyToFoodChain([FromBody] TxMSAGrading body)
{ ... }
What I've tried:
[JsonConverter(typeof(DateFormatConverter), "MM/dd/yyyy hh:mm:ss")]
public DateTime KillDate { get; set; }
Error:
The JSON value could not be converted to System.DateTime
Input String:
{"GradeDate": "08/24/2020 01:36:00", "KillDate" : "08/24/2020 00:00:00", ... }
Additional Information:
I cannot change the model. So it will always be parsed in to be converted to a Date-Time.
There are 500+ fields in the model. I can't explicitly convert every Date-time field.
DateTime fields will always have the same format.
One idea is to defer parsing until after the raw string is captured in your model. This allows deserialization to succeed more reliably and for you to have control over the parsing. For example, an updated model:
public string KillDate { get; set; }
public DateTime KillDateValue => DateTime.TryParse(KillDate, out DateTime parsed) ? parsed : DateTime.MinValue;
public bool KillDateParsed => KillDateValue != DateTime.MinValue;
If parsing succeeds, KillDateParsed will be true and you'll have the parsed value in KillDateValue. DateTime.TryParse can also be provided a specific pattern to match.

Json field name with forward slash

I have to deserialize json into C# classes but many of the json field names have a forward slash in them.
I've searched this site to see if anyone else has asked a similar question but nothing came up.
json:
{
"start": "2019-10-24T10:37:27.590Z",
"end": "2019-10-24T11:00:00.000Z",
"requests/duration": {
"avg": 3819.55
}
}
c#
class Metrics
{
public DateTime start = DateTme.MinValue;
public DateTime end = DateTme.MinValue;
public RequestsDuration requestsduration = null;
}
class RequestsDuration
{
public double avg = 0.0;
}
...
Metrics data = JsonConvert.DeserializeObject<Metrics>(json);
The "requests/duration" in the json does not deserialize into the Metrics class.
I can do this before deserializing:
json = json.Replace("requests/duration","requestsduration")
but I was wondering if there was a cleaner way.
Does json.net provide a way to deal with special characters in json fields?
You can customize field names for the json by using JsonProperty attribute.
For the Metrics class you can do following:
class Metrics
{
public DateTime start = DateTme.MinValue;
public DateTime end = DateTme.MinValue;
[JsonProperty("requests/duration")]
public RequestsDuration requestsduration = null;
}

DataMember Property with Custom Get?

I'm going by this tutorial and trying to figure out how to have a DataMember without an auto property. Basically I have a field is a date time in epoch format and I want the property to be a DateTime so I'm trying to do the conversion in the property's get. I'm not sure how to format this exactly.
Since Code was requested please look at the following. :
// The date looks like this in the JSON
"someEpochDateTime": 1428785212000,
// I thought I could work around it using the following code, however
// I get a warning saying someEpochDateTime is never set.
[DataMember(Name = "someEpochDateTime")]
private long someEpochDateTime;
public DateTime test
{
get { return DateTimeConverter.FromUnixTime(someEpochDateTime); }
}
Using FromUnixTime
like this you can create datereturn property this will return date
[DataContract]
public class Mycontractclass
{
// Apply the DataMemberAttribute to the property.
[DataMember]
public DateTime datereturn
{
get
{
return this.dateCreated.HasValue
? this.dateCreated.Value
: DateTime.Now;
}
set { this.dateCreated = value; }
}
private DateTime? dateCreated = null;
}
Apparently my last edit actually works as a solution, I just get a compiler warning for some reason.
[DataMember(Name = "someEpochDateTime")]
private long someEpochDateTime;
public DateTime test
{
get { return DateTimeConverter.FromUnixTime(someEpochDateTime); }
}

Convert Date into JSON object in c#

I've created a C# class with a static method that convert's any object to a JSON object. I've used JavaScriptSerializar for this. Here is my code
public class JS
{
public static string GetJSON(object obj)
{
JavaScriptSerializer js = new JavaScriptSerializer();
string retJSON = js.Serialize(obj);
return retJSON;
}
}
I've another class that have only two property, Date & Remark. Here is my class
public class RemarkData
{
public DateTime Date { set; get; }
public string Remark { set; get; }
}
Now, I'm converting a object of the RemarkData class into JSON using following code
JS.GetJSON(objRemarkData);
Here is the output I'm getting
{"Date":"/Date(1389403352042)/","Remark":"Sme Remarks"}
Here is the output that I need
{"Date":1389403352042,"Remark":"Some Remarks"}
What should I do tho get that kind of output? Any help ?
double ticks = Math.Floor(objRemarkData.Date.ToUniversalTime()
.Subtract(new DateTime(1970, 1, 1))
.TotalMilliseconds);
var newob = new { Date =ticks, Remark = objRemarkData.Remark};
JS.GetJSON(newob);
You could try JSON.NET, it serializes Date into ISO string.
public class JS
{
public static string GetJSON(object obj)
{
string retJSON = JsonConvert.SerializeObject(obj);
return retJSON;
}
}
Actually, you can use it directly, don't need to wrap inside another function.
This is also how asp.net web api serializes date objects. For more information why ISO string is a good choice, check out this link http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx
This long number is "milliseconds since epoch". We can convert this to normal javascript date by using the following snippet as explained in another so post Converting .NET DateTime to JSON
var d = new Date();
d.setTime(1245398693390);
document.write(d);
One can also use a nice library from http://blog.stevenlevithan.com/archives/date-time-format with the following snippet ..
var newDate = dateFormat(jsonDate, "dd/mm/yyyy h:MM TT");

Specifying a custom DateTime format when serializing with Json.Net

I am developing an API to expose some data using ASP.NET Web API.
In one of the API, the client wants us to expose the date in yyyy-MM-dd format. I don't want to change the global settings (e.g. GlobalConfiguration.Configuration.Formatters.JsonFormatter) for that since it is very specific to this client. And I do developing that in a solution for multiple clients.
One of the solution that I could think of is to create a custom JsonConverter and then put that to the property I need to do the custom formatting
e.g.
class ReturnObjectA
{
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime ReturnDate { get;set;}
}
Just wondering if there is some other easy way of doing that.
You are on the right track. Since you said you can't modify the global settings, then the next best thing is to apply the JsonConverter attribute on an as-needed basis, as you suggested. It turns out Json.Net already has a built-in IsoDateTimeConverter that lets you specify the date format. Unfortunately, you can't set the format via the JsonConverter attribute, since the attribute's sole argument is a type. However, there is a simple solution: subclass the IsoDateTimeConverter, then specify the date format in the constructor of the subclass. Apply the JsonConverter attribute where needed, specifying your custom converter, and you're ready to go. Here is the entirety of the code needed:
class CustomDateTimeConverter : IsoDateTimeConverter
{
public CustomDateTimeConverter()
{
base.DateTimeFormat = "yyyy-MM-dd";
}
}
If you don't mind having the time in there also, you don't even need to subclass the IsoDateTimeConverter. Its default date format is yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK (as seen in the source code).
You could use this approach:
public class DateFormatConverter : IsoDateTimeConverter
{
public DateFormatConverter(string format)
{
DateTimeFormat = format;
}
}
And use it this way:
class ReturnObjectA
{
[JsonConverter(typeof(DateFormatConverter), "yyyy-MM-dd")]
public DateTime ReturnDate { get;set;}
}
The DateTimeFormat string uses the .NET format string syntax described here: https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
It can also be done with an IsoDateTimeConverter instance, without changing global formatting settings:
string json = JsonConvert.SerializeObject(yourObject,
new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
This uses the JsonConvert.SerializeObject overload that takes a params JsonConverter[] argument.
Also available using one of the serializer settings overloads:
var json = JsonConvert.SerializeObject(someObject, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-ddThh:mm:ssZ" });
Or
var json = JsonConvert.SerializeObject(someObject, Formatting.Indented, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-ddThh:mm:ssZ" });
Overloads taking a Type are also available.
There is another solution I've been using. Just create a string property and use it for json. This property wil return date properly formatted.
class JSonModel {
...
[JsonIgnore]
public DateTime MyDate { get; set; }
[JsonProperty("date")]
public string CustomDate {
get { return MyDate.ToString("ddMMyyyy"); }
// set { MyDate = DateTime.Parse(value); }
set { MyDate = DateTime.ParseExact(value, "ddMMyyyy", null); }
}
...
}
This way you don't have to create extra classes. Also, it allows you to create diferent data formats. e.g, you can easily create another Property for Hour using the same DateTime.
With below converter
public class CustomDateTimeConverter : IsoDateTimeConverter
{
public CustomDateTimeConverter()
{
DateTimeFormat = "yyyy-MM-dd";
}
public CustomDateTimeConverter(string format)
{
DateTimeFormat = format;
}
}
Can use it with a default custom format
class ReturnObjectA
{
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime ReturnDate { get;set;}
}
Or any specified format for a property
class ReturnObjectB
{
[JsonConverter(typeof(CustomDateTimeConverter), "dd MMM yy")]
public DateTime ReturnDate { get;set;}
}
public static JsonSerializerSettings JsonSerializer { get; set; } = new JsonSerializerSettings()
{
DateFormatString= "yyyy-MM-dd HH:mm:ss",
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new LowercaseContractResolver()
};
Hello,
I'm using this property when I need set JsonSerializerSettings
Some times decorating the json convert attribute will not work ,it will through exception saying that "2010-10-01" is valid date. To avoid this types i removed json convert attribute on the property and mentioned in the deserilizedObject method like below.
var addresss = JsonConvert.DeserializeObject<AddressHistory>(address, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd" });

Categories