How to let Newtonsoft.Json allow Json DateTime conversion with Timezone info? - json

I have a MVC3 project that manages events' dates. The problem is that when I write a JsonResult
//...
var StartDate=new DateTime(1999,12,10,2,3,40);
return Json(StartDate,JsonBehavior.AllowGet);
the response's body format is something similar to
"StartDate":"\/Date(1374962232247)\/"
This result is giving me a date in the last day according to the server timezone, Instead of returning something like
"StartDate":"\/Date(1374962232247-0600)\/"
which contains some server timezone info!
I can't follow the SHanselman's post(like it but It seems not appropriated)!
So, can someone tell me how to let Newtonsoft.Json.5.0.6 packages convert Json DateTime with Timezone info?
Kind Regards

I think this link should help you with setting up MVC3 project working with Newtonsoft Json Serializer. For ISO date time formatter you should change the following lines in the JsonNetResult constructor.
public JsonNetResult()
{
Formatting = Formatting.None;
var settings = new JsonSerializerSettings();
settings.Converters.Add(new IsoDateTimeConverter());
SerializerSettings = settings;
JsonRequestBehavior = JsonRequestBehavior.DenyGet;
}
You have to derive your controllers from BaseController to use the custom result.
hope this helps.

Related

Timespan type cannot be mapped correctly when using Servicestack CsvSerializer

I am trying to convert list of objects to comma seperated string through SerializeToCsv method of Servicestack. However, i realized that timespan cannot be converted correctly. Forexample, my timespan value is 19:00:00, however it converts as PT19H. You can see the code below. I can convert timespan to string by adding string property and change timespan to string at runtime in object, however i thought that there would be better way in Servicestack and could not find anything on internet. Thanks in advance!
public string Convert()
{
var data = _table.Get();
CsvSerializer.UseEncoding = PclExport.Instance.GetUTF8Encoding(true);
var csvStr = CsvSerializer.SerializeToCsv(data);
return csvStr;
}
This is the default serialization of TimeSpan which uses the XSD duration format, e.g. 19 hours = PT19H, i.e. a Period of 19 Hours.
You can change the serialization format with:
JsConfig.TimeSpanHandler = TimeSpanHandler.StandardFormat;

ServiceStack.Text CSV serialization of IEnumerable<object> ignores custom serialization functions

Firstly, please forgive any rookie mistakes here - I'm not a regular poster I'm afraid.
Now on to the nitty gritty...
I am trying to use ServiceStack.Text to serialize objects to CSV. If I keep it simple, everything works as expected when serializing objects of a known type.
However I want to serialize many objects and I don't know the type at runtime so I am writing a reusable component where all data is treated as a System.Object. We already do this same routine for Json serialization without problems. But CsvSerializer appears to handle objects differently during serialization.
Sample code
public void TestIEnumerableObjectSerialization()
{
var data = GenerateSampleData();
JsConfig<DateTime>.SerializeFn =
time => new DateTime(time.Ticks, DateTimeKind.Utc).ToString("yyyy-MM-dd HH:mm:ss");
var csv = CsvSerializer.SerializeToCsv(data);
Console.WriteLine(csv);
Assert.Equal("DateTime\r\n"
+ "2017-06-14 00:00:00\r\n"
+ "2017-01-31 01:23:45\r\n",
csv);
}
object[] GenerateSampleData()
{
return new object[] {
new POCO
{
DateTime = new DateTime(2017,6,14)
},
new POCO
{
DateTime = new DateTime(2017,1,31, 01, 23, 45)
}
};
}
public class POCO
{
public DateTime DateTime { get; set; }
}
The result of this code is that the custom serialization function is not invoked, and the DateTime is written out using the standard ToString() method.
The cause?
The CsvWriter.Write method is inspecting the type of the records and if the type is Object it is treated as a Dictionary<string, object> and CsvDictionaryWriter generates the output.
In turn, CsvDictionaryWriter uses the ToCsvField() extension method to write each property a record.
The problem is that ToCsvField() converts the value of each property to a string using ToString() meaning no custom serialization is performed.
JsonSerializer uses TypeSerializer.SerializeToString(text) to serialize the properties of an Object using any configured custom serialization functions; but this doesn't happen with CsvSerializer.
A possible solution?
Without complicating CsvSerializer, the ToCsvField() extension method could be updated to use TypeSerializer to handle the serialization to a string. Here is what I've been testing with so far:
public static object ToCsvField(this object text)
{
var textSerialized = TypeSerializer.SerializeToString(text).StripQuotes();
return textSerialized == null || !CsvWriter.HasAnyEscapeChars(textSerialized)
? textSerialized
: string.Concat
(
CsvConfig.ItemDelimiterString,
textSerialized.Replace(CsvConfig.ItemDelimiterString, CsvConfig.EscapedItemDelimiterString),
CsvConfig.ItemDelimiterString
);
}
So far I haven't come across an issue with this change, although someone may prefer not to allocate a new intermediate variable before the return statement.
Hopefully that is enough information, so on to my questions...
Has anyone else experienced this issue?
Am I doing something wrong and should I be serializing Objects a different way?
If this is a suitable fix/implementation of TypeSerializer, what are the chances of this being addressed in an update to ServiceStack.Text? I would raise an issue on GitHub but the ServiceStack.Text repo doesn't let me raise issues.
Thanks in advance.

Details about the json:Array feature of Newtonsoft.JSON XML to JSON converter

Referencing this example of using "json:Array": Converting between JSON and XML
I have two questions:
Does the namespace have to be "json"? I.e. if ns2 matched back to
"xmlns:ns2='http://james.newtonking.com/projects/json'" would that work?
Can the namespace be omitted? Can I just put "Array='true'"?
I'm about to try to test by trial and error, but thought maybe somebody would know the answer, or someone in the future would like to know.
Not that it matters a whole lot, but my XML is being generated by BizTalk 2010 and I'm using a WCF CustomBehavior to call NewtonSoft as follows:
private static ConvertedJSON ConvertXMLToJSON(string xml)
{
// To convert an XML node contained in string xml into a JSON string
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
ConvertedJSON convertedJSON = new ConvertedJSON();
convertedJSON.JSONtext = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None);
convertedJSON.rootElement = doc.DocumentElement.Name;
return convertedJSON;
}
Looks like the namespace has to be exactly what they provide:
string xmlToConvert2 = "<myRoot xmlns:json='http://james.newtonking.com/projects/json'><MyText json:Array='true'>This is the text here</MyText><Prices><SalesPrice>10.00</SalesPrice></Prices></myRoot>";
string strJSON2 = ConvertXMLToJSON(xmlToConvert2);
As with normal xml, the namespace prefix can be any value. The follow worked equally as well as the above.
string xmlToConvert3 = "<myRoot xmlns:abc='http://james.newtonking.com/projects/json'><MyText abc:Array='true'>This is the text here</MyText><Prices><SalesPrice>10.00</SalesPrice></Prices></myRoot>";
string strJSON3 = ConvertXMLToJSON(xmlToConvert3);

grails rest client converting string to java.util.Date

I'm trying to use a rest-service created in grails 2.5.5 which has a Date property as follows:
import grails.rest.*
#Resource(uri='/restDomain', readOnly=true)
class RestDomain {
Date myDate
}
But when calling from another grails app (v2.5.5 or v3.1.9) like this:
new RestBuilder().get('http://localhost:8080/restApp/restDomain.json').json.collect {
new RestDomain(it)
}
I get a Cannot cast object '2016-01-20T12:36:57Z' with class 'java.lang.String' to class 'java.util.Date' error.
I've already added this in application.yml (grails v3.1.9) at the very bottom of the file
---
grails:
databinding:
dateFormats:
- yyyy-MM-dd'T'HH:mm:ssX
- yyyy-MM-dd'T'HH:mm:ss.SSSX
and this in Config.groovy (grails v2.5.5)
grails.databinding.dateFormats = ["yyyy-MM-dd'T'HH:mm:ssX", "yyyy-MM-dd'T'HH:mm:ss.SSSX"]
but doesn't seem to work at all
Note: In both client apps I have the corresponding src/groovy/restApp/RestDomain.groovy class as follows:
package restApp
class RestDomain {
Date myDate
}
Note 2: The grails 3.1.9 client app has compile 'org.grails:grails-datastore-rest-client:6.0.0.M1' dependency the in build.gradle dependencies section, and the grails 2.5.5 client app has compile ':rest-client-builder:2.1.1' in the BuildConfig.groovy plugins section
Any help getting it to work in a Grails 2.5.x or Grails 3.1.x app would be really appreciated
The 'Z' at the end of your date string signifies that the time zone is UTC which is not a valid ISO 8601 time zone specification that you could parse with the 'X' in your time formats. It is a literal that should be parseable with
yyyy-MM-dd'T'HH:mm:ss'Z'
Adding an answer to provide a workaround on how I resolved this, but I will not mark it as the accepted answer because it is not the ideal way to solved it, so here it is:
Added this in my client controller (I guess that the bindData method is the key here):
new RestBuilder().get('http://localhost:8080/restApp/restDomain.json').json.collect {
def restDomainInstance = new RestDomain()
bindData(restDomainInstance, it)
restDomainInstance
}
and changed RestDomain.groovy to this
package restApp
import java.text.SimpleDateFormat
import org.grails.databinding.BindUsing
class RestDomain {
#BindUsing({ obj, source ->
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX")
.parse(source.getPropertyValue('myDate'))
})
Date myDate
}
The X in the SimpleDateFormat is for recognizing the timezone as UTC, so the jvm converts it to its current timezone later (in my case: -04:00 GMT)

Entity framework - WCF - return JSON how to do this?

I have all the POCO entities produced from my database. I created an IXXX interface, a XXX class to define the structure of the table I want to return from my service, and a XXX class to do the query and the return part for the interface.
My question is regarding the elements I need to add to this setup in order to return clean JSON from my web service.
I'm a beginner so all points of view are welcome. Thanks!
You can define XXXDto classes which are having a clean format for your client needs. And then map the domain/endity classes to Dto objects and serialize them using WCF.
Or you can create WCF OData services to expose the service as OData source.
try this:
To return Json data [in EF]:
add reference 'System.Runtime.Serialization' to the project
write code like below:
using System.Web.Script.Serialization;
public string getValuesJson()
{
JavaScriptSerializer js = new JavaScriptSerializer();
MyDBEntities ctx = new MyDBEntities();
var myValues = (from m in ctx.TestEntity
where (m.id == 22)
select m).ToList();
return js.Serialize(myValues);
}
you can also check whether Json string is valid or not at http://jsonlint.com/