Запрос Космоса БД Cosmos Сериализует / Десериализует Сбои с NewtonSoft JsonConvert

Я пытаюсь упаковать несколько объектов параметров для отправки в функцию HttpTrigger функций Azure. Часть пакета - это объект RequestOptions, необходимый для действий Cosmos DB. Должно быть очень простым, сериализовать объект и десериализовать на стороне функций. Проблема в том, что JsonConvert не будет сериализовать объект PartitionKey объекта RequestOptions. Класс запечатан. есть идеи как это сделать? Мой код простой тест. Создать объект добавить ключ раздела. Сериализуйте это. Десериализовать его и проверить значение 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, и код работает. Таким образом, проблема заключается в сериализации, производящей NULL для ключа раздела. Если это не может быть сериализовано, какой смысл?

1 ответ

PartitionKey Класс не предоставляет никаких открытых членов, которые Json.Net сможет "увидеть" для сериализации в JSON. Поэтому, когда вы пытаетесь сериализовать его напрямую, он появляется как пустой объект {} в JSON. При десериализации Json.Net пытается использовать PartitionKey конструктор, но не знает, что заполнить для keyValue параметр, поэтому он просто использует null, Так что это объясняет результат, который вы видите.

Я заметил, что PartitionKey Кажется, что у самого класса есть поддерживаемый способ конвертировать его в JSON и обратно, используя его ToString() а также FromJsonString() методы. Так что если вы хотите включить этот класс в большую сериализацию, вы можете сделать простой 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());
    }
}

Чтобы использовать конвертер, просто передайте экземпляр SerializeObject а также DeserializeObject<T> методы как это:

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

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

Скрипка: https://dotnetfiddle.net/Jqo7mg

Другие вопросы по тегам