Запрос Космоса БД Cosmos Сериализует / Десериализует Сбои с NewtonSoft JsonConvert - PullRequest
0 голосов
/ 13 января 2019

Я пытаюсь упаковать несколько объектов параметров для отправки в функцию 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 Ответ

0 голосов
/ 13 января 2019

Класс 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

...