I'm working on a Windows 8 Metro application that references a c# WinRT project. Among other things, the c# project makes web requests to an Azure service to perform CRUD operations against a SQL Azure database.
When performing a POST operation on the service, I'm serializing an instance of a class and putting it in the body of the request.
public sealed class Foo
{
int FooId { get; set; }
DateTimeOffset FooDate { get; set; }
}
When this is serialized using the DataContractJSONSerializer, the result is something like this:
{"FooId":1,"FooDate":{"DateTime":"/Date(1342732970000)/","OffsetMinutes":-420}}
FYI that this is 7/19/2012 2:22:50PM -07:00.
OK great ... Only problem is that the Azure service is expecting just a DateTime, not a DateTimeOffset. I don't own the Azure service so I can't change its behavior.
So (ignoring that I'm losing the offset) what I need is this to serialize into:
{"FooId":1,"FooDate":"/Date(1342732970)/"}
My first approach was to add a new aliased DateTime property/datamember to the class with a getter that returns the DateTime portion of the DateTimeOffset. However, WinRT doesn't support the DateTime type.
There are a couple of hacky ways to get around this, but I wanted to see if there's an elegant way to do this before resorting to one of these:
Regex on the serialization result before the POST
String property on the class that returns a JSON formatted date
Thanks
I ended up implementing a property on the class with a getter that formats the date appropriately.
I decorated the Foo field with the IgnoreDataMember attribute so that it gets ignored during serialization. I then added a new field and gave it the alias of Foo for serialization.
Thanks
Related
I am developing a ASP.NET Core 3.1 website and I have data in a Dictionary<string, object> that I want to Serialize/Deserialize using Microsoft System.Text.Json (I am new to Json serialize/deserialize in fact). The data comes from a PostgreSQL DB query and one of the returned values is a comma-separated list of integers (converted to string) that results from the STRING_AGG function. The image below shows one of the entries of the Dictionary:
I serialize it using the following code. Please note that I have tried both Microsoft System.Text.Json and Newtonsoft.
jsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(result);
//jsonResult = JsonSerializer.Serialize(result);
The data in the Dictionary should be deserialized according to the following class structure:
I use the following code:
//IEnumerable<SeccGralContenidoViewModel> seccGralContenido = JsonSerializer.Deserialize<IEnumerable<SeccGralContenidoViewModel>>(_seccGralContenidoRepository.Read());
IEnumerable<SeccGralContenidoViewModel> seccGralContenido = Newtonsoft.Json.JsonConvert.DeserializeObject <IEnumerable<SeccGralContenidoViewModel>>(_seccGralContenidoRepository.Read());
However, an exception is thrown when deserializing no matter if I use Newtonsoft or System.Text.Json:
I am originally using System.Text.Json namespace but I also tried using Newtonsoft. After analyzing a bit deeper, I see that the problem could be the way in which data is saved to the Dictionary but I have not found a workaround.
If you don't want to write a custom converter then the simplest solution is to introduce another property:
public string CategoriasContenidolds {get; set;}
private static char delimiter = ',';
[JsonIgnore]
public string[] CategoriasContenidolds_Collection
{
get => CategoriasContenidolds.Split(delimiter).Select(item => item.Trim()).ToArray();
set => CategoriasContenidolds = string.Join(delimiter, value);
}
The serializer will use the CategoriasContenidolds property during serialization and deserialization
You should use CategoriasContenidolds_Collection (or name whatever you want) in your business logic
By explicitly marking this property with JsonIgnore the serializer will ignore that
I could solve my issue by directly getting JSON formatted results from queries. PostgreSQL does an excellent job. This way I also avoid performing a 2-step process: first, getting the query result; second, serializing to JSON.
I have an Azure Function that receives some JSON from a queue, fx.
{"FromDate":"2020-05-26T07:15:00.3714532+00:00","ToDate":"2020-06-25T07:15:00.3714532+00:00"}
Using System.Text.Json.JsonSerializer I am trying to de-serialize this JSON into an object of the following type:
public class DateRange
{
public DateTime? FromDate { get; set; }
public DateTime? ToDate { get; set; }
}
The de-serialization:
var dateRange = JsonSerializer.Deserialize<DateRange>(json);
This does not work in Azure - FromDate and ToDate are always parsed to the default date 1/1/0001 12:00:00 AM. The strange thing is that the JSON is created from another Azure Function with JsonSerializer.Serialize(dateRange).
But if I run the Azure Function locally it does work.
It seems from the documentation, that the date/time format
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm"
sent in the JSON is supported (which makes sense because it is created by JsonSerializer.Serialize()).
Why does it fail to de-serialize my JSON? And why does it work locally but not on Azure?
Are you using a queue which is bonded as an input to your function (and triggers it)? Could you show how you write the serialized string to queue and then how you read it from the queue before deserialization?
Are you sure that the string which is taken from the message looks exactly like in your example?
I am asking because the messages in queues bound to functions are expected to be base64 encoded which causes a lot of issues if you forget about this. And since it works locally, I would blame the transport mechanism (queue) for changing the behavior.
I try to realize database access decorator based on Expression types. So, I've already tried many different json serializing libraries, started from Newtonsoft Json till DataContractJsonSerializator and etc.
1) Most of serializators crash on Expression type serialization (including System.Text.Json.Serialization).
2) Newtonsoft.JsonSerializer successfully serialize Expression<Func<User, bool>> test = e => e.Id == sameUser.Id, where User is the class like:
public class User
{
public Guid Id { get; set; }
public string Fullname { get; set; }
}
and sameUser is an object of User class.
But Newtonsoft.JsonSerializer produces string of ~169-200 millions symbols. I don't know does Newtonsoft.JsonSerializer correctly deserialize this json of the other side becauseof the size. Ofcourse, I've tried to use different serializing options.
3) ServiceStack.Text.JsonSerializer successfully serialize Expression<Func<User, bool>> test = e => e.Id == sameUser.Id with normal json size (approx 2-3 thousands symbols), but on the deserialization Expression.Body always null after deserialization (and this really strange - serialized json has it well-serialized).
4) Serialize.Linq successfully passed the test.
I want to understand, what the reason of this strange behavior of main serializers like Newtonsoft, ServiceStack, Microsoft, etc?
P.S. I'ven't tested protobuf-net and MessagePack yet, I'll do this soon,but think they have the same troubles with Expression class object serialization/deserialization.
Expression has cyclical dependencies an non serializable references that is not suitable for serialization. If you want to serialize the debug string representation of an Expression do that in your code and serialize the string, don’t expect serialization libraries to attempt to serialize a non-serializable class that’s impossible to deserialize.
If you want to serialize code, send raw source code and use Roslyn or Code DOM to execute the source code received, you’ll need to validate any untrusted user code for potential security vulnerabilities or unwanted behavior before evaluating it.
How do I configure the JSON dates produced by my Web API 2 Controller to include the time zone?
Data type used for dates in SQL Server are datetime and I don’t have the option of changing the Legacy database.
Breeze uses Json.NET to serialize/deserialize json. You can configure the serializer settings that Breeze uses by creating a custom class that inherits from Breeze.ContextProvider.BreezeConfig. Breeze will automatically discover this class and create an instance of it for all configuration tasks.
Something like this:
public class CustomBreezeConfig : Breeze.ContextProvider.BreezeConfig
{
protected override Newtonsoft.Json.JsonSerializerSettings CreateJsonSerializerSettings()
{
var ret = base.CreateJsonSerializerSettings();
ret.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
// ret.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;
return ret;
}
}
But before you go down this path please read this (the response specifically):
breezejs: date is not set to the right time
Try returning your DateTime formatted with .ToString() and use a custom date and time format like "K". See: http://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx#KSpecifier for more information.
I have a couple of POJOs which looks like this:
class Items {
List<Item> items;
public List<Item> getItems() {
return items;
}
...
}
class Item {
String name;
Date insertionDate;
...
}
I want to be able to serialize the Date field in Item using a custom format (add a prefix to the date, something like "Date:xxx"), but I don't want to do that always (as it's used by other consumers which don't require this prefix), only in specific cases.
If I annotate Item's getInsertionDate() with#JsonSerialize(using = CustomDateSerializer.class) I can probably make this work, however, I don't want to do that since I don't always want to serialize this field using this method, only in a specific case.
So ideally, I would do this in my controller which does want to customize the serialization:
#JsonSerialize(using = CustomDateSerializer.class)
public List<Item> getItems() {
....
}
where CustomDateSerializer extends SerializerBase<Date> and Jackson would figure out that it should serialize each item in the List using the default serializer, and when it hits a Date object it should use my custom serializer. Of course this does not work since that's not how #JsonSerialize is used, but is there a way to make this work other than to wrap Item with a wrapper and use that wrapper when I want the custom serialization? Am I thinking about this the wrong way and there's another way to do this?
Note that I'm using Spring MVC so I'm not calling the serialization directly.
Any help would be much appreciated :)
The problem is that Jackson does not see the annotations on getItems() if it is a service end point method; it is typically only passed type List<Item> that Spring determines. With JAX-RS (like Jersey), annotations associated with that method are passed, however (and perhaps Spring has some way as well); although it then requires bit more support from integration code (for JAX-RS, Jackson JAX-RS JSON provider module) to pass that along.
It might be easier to actually create a separate POJO (and not pass List types) so that you can add necessary annotations.
If you were using Jackson directly, you could also use ObjectWriter and specify default date format to use. But I don't know if Spring allows you to do that (most frameworks do not and only expose configurability of ObjectMapper).
One more note -- instead of custom serializer (and/or deserializer), you can also use simple annotations with Dates (and on Jackson 2.x):
public class DateStuff {
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="'Date:'yyyy'-'MM'-'dd")
public Date date;
}
to specify per-property format override.