I am trying to package a number of parameter objects to send to an Azure Functions HttpTrigger function. Part of the package is a RequestOptions object necessary for Cosmos DB actions. Should be very simple, serialize the object and deserialize on the functions side. Problem is JsonConvert will not serialize the PartitionKey object of the RequestOptions object. The class is sealed. Any idea how to do this? My code is a simple test. Create an object add a partition key. Serialize it. Deserialize it and check the value of the PartitionKey. It is always null. I haven't been able to find an answer to this. It seems like a possible bug in the RequestOptions class preventing JsonConvert from serializing.
public static void Main(string[] args)
{
var partitionKeyValue = "39393939"; // Some partition key in Cosmos DB collection
var requestOptions = new RequestOptions
{
PartitionKey = new PartitionKey(partitionKeyValue)
};
var data = JsonConvert.SerializeObject(requestOptions);
// send data to Azure Functions
var requestOptions1 = JsonConvert.DeserializeObject<RequestOptions>(data);
}
I am using VS debugger to inspect the values. I know that I can use the PartitionKey because I can code it directly in the Azure Functions function and the code works. So the problem is in the serialization producing a NULL for the partition key. If it cannot be serialized, what is the point?
The PartitionKey
class does not expose any public members that Json.Net would be able to "see" in order to serialize into the JSON. Therefore, when you try to serialize it directly, it comes out as an empty object {}
in the JSON. On deserialization, Json.Net tries to use the PartitionKey
constructor but does not know what to fill in for the keyValue
parameter, so it just uses null
. So that explains the result you are seeing.
I notice that the PartitionKey
class itself seems to have a supported way to convert it to and from JSON by using its ToString()
and FromJsonString()
methods. So if you want to incorporate this class into a larger serialization, you could make a simple JsonConverter
that would allow it to work:
public class PartitionKeyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(PartitionKey);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
string s = (string)reader.Value;
return s != null ? PartitionKey.FromJsonString(s) : null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
}
To use the converter, just pass an instance to the SerializeObject
and DeserializeObject<T>
methods like this:
var data = JsonConvert.SerializeObject(requestOptions, new PartitionKeyConverter());
var requestOptions1 = JsonConvert.DeserializeObject<RequestOptions>(data, new PartitionKeyConverter());
Fiddle: https://dotnetfiddle.net/Jqo7mg