I have the following scenario: I am using WebAPI and returning JSON results to the consumer based on a model. I now have the additional requirement to serialize the models to base64 to be able to persist them in cache and/or use them for auditing purposes. Problem is that when I add the [Serializable]
attribute to the model so for converting the the model to Base64, the JSON output changes as follows:
The Model:
[Serializable]
public class ResortModel
{
public int ResortKey { get; set; }
public string ResortName { get; set; }
}
Without the [Serializable]
attribute the JSON output is:
{
"ResortKey": 1,
"ResortName": "Resort A"
}
With the [Serializable]
attribute the JSON output is:
{
"<ResortKey>k__BackingField": 1,
"<ResortName>k__BackingField": "Resort A"
}
How would I be able to use the [Serializable]
attribute without changing the output of the JSON?
It is not necessary to use this attribute if a given type implements the System. Runtime. Serialization. ISerializable interface, which indicates that a class provides its own methods for serialization.
When you apply the SerializableAttribute attribute to a type, all private and public fields are serialized by default. You can control serialization more granularly by implementing the ISerializable interface to override the serialization process.
So, serialization converts the object into a shareable format. With serialization, we can transfer objects: Between client and server via REST APIs or GRPC. Over the network for messaging systems like Kafka or RabbitMQ. Through firewalls as JSON or XML strings.
Using [FromUri] To force Web API to read a complex type from the URI, add the [FromUri] attribute to the parameter. The following example defines a GeoPoint type, along with a controller method that gets the GeoPoint from the URI.
By default, Json.NET ignores the Serializable
attribute. However, according to a comment to this answer by Maggie Ying (quoted below because comments are not meant to last), WebAPI overrides that behavior, which causes your output.
Json.NET serializer by default set the IgnoreSerializableAttribute to true. In WebAPI, we set that to false. The reason why you hit this issue is because Json.NET ignores properties: "Json.NET now detects types that have the SerializableAttribute and serializes all the fields on that type, both public and private, and ignores the properties" (quoted from james.newtonking.com/archive/2012/04/11/…)
A simple example that demonstrates the same behavior without WebAPI can look like this:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
namespace Scratch
{
[Serializable]
class Foo
{
public string Bar { get; set; }
}
class Program
{
static void Main()
{
var foo = new Foo() { Bar = "Blah" };
Console.WriteLine(JsonConvert.SerializeObject(foo, new JsonSerializerSettings()
{
ContractResolver = new DefaultContractResolver()
{
IgnoreSerializableAttribute = false
}
}));
}
}
}
There are several ways around this behavior. One is to decorate your model with a plain JsonObject
attribute:
[Serializable]
[JsonObject]
class Foo
{
public string Bar { get; set; }
}
Another way is to override the default settings in your Application_Start()
. According to this answer, the default settings should do it:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings();
If that doesn't work, you could be explicit about it:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings()
{
ContractResolver = new DefaultContractResolver()
{
IgnoreSerializableAttribute = true
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With