Cosmos DB RequestOptions的NewtonSoft JsonConvert序列化/反序列化失败

时间:2019-01-13 10:06:08

标签: json json.net azure-cosmosdb jsonconvert

我正在尝试打包许多参数对象以发送给Azure Functions HttpTrigger函数。软件包的一部分是Cosmos DB操作必需的RequestOptions对象。应该非常简单,在功能方面对对象进行序列化和反序列化。问题是JsonConvert不会序列化RequestOptions对象的PartitionKey对象。该类是密封的。任何想法如何做到这一点?我的代码是一个简单的测试。创建一个对象添加一个分区键。序列化它。将其反序列化并检查PartitionKey的值。始终为空。我还没有找到答案。似乎RequestOptions类中可能存在一个错误,导致JsonConvert无法序列化。

    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);
    }

我正在使用VS调试器检查值。我知道我可以使用PartitionKey,因为我可以直接在Azure Functions函数中对其进行编码,并且代码可以正常工作。因此,问题在于序列化会为分区键生成NULL。如果无法序列​​化,那有什么意义?

1 个答案:

答案 0 :(得分:3)

PartitionKey类未公开Json.Net能够“看到”以序列化为JSON的任何公共成员。因此,当您尝试直接对其进行序列化时,它会在JSON中作为空对象{}出现。在反序列化方面,Json.Net尝试使用PartitionKey构造函数,但不知道为keyValue参数填写什么,因此它仅使用null。这样可以解释您所看到的结果。

我注意到PartitionKey类本身似乎具有受支持的方法,可以使用其ToString()FromJsonString()方法将其与JSON相互转换。因此,如果要将此类合并到更大的序列化中,则可以制作一个简单的JsonConverter使其可以工作:

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());
    }
}

要使用转换器,只需将实例传递给SerializeObjectDeserializeObject<T>方法,如下所示:

var data = JsonConvert.SerializeObject(requestOptions, new PartitionKeyConverter());

var requestOptions1 = JsonConvert.DeserializeObject<RequestOptions>(data, new PartitionKeyConverter());

提琴:https://dotnetfiddle.net/Jqo7mg