Сериализация Dictionary<string, object>
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.05.20 15:39
Оценка:
Всем привет.

Казалось бы, на первый взгляд, простейшая задача. Есть Dictionary<string, object>. Нужно записать его в ветку реестра текущего пользователя и восстановить потом в обратно Dictionary<string, object>. Беда только в том, что в object могут быть разные типы. В том числе целые могут быть разных тпов: int, long, uint... Там могут появляться только примитивные типы или к ним сводимые (строки, целые разных типов, энумы, даты), т.е. типы колонок БД. Вот только важно, чтобы если был long, чтобы они десерелизоваля.

Решил сереализнуть его через Newton json, но он информацию о типах не особо сохраняет, так что при десериализации вместо, скажем, uint или long получаем int, а это не приемлемо.

Добился желаемого только через BinaryFormatter. Но он порождает очень некомпактный выхлоп. Тратить время на зипование тоже не хочется.

Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Сериализация Dictionary<string, object>
От: pilgrim_ Россия  
Дата: 30.05.20 16:13
Оценка: 53 (1)
Здравствуйте, VladD2, Вы писали:

VD>Решил сереализнуть его через Newton json, но он информацию о типах не особо сохраняет, так что при десериализации вместо, скажем, uint или long получаем int, а это не приемлемо.

..
VD>Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?

Попробуй при сериализации использовать JsonSerializerSettings.TypeNameHandling.All

All — Json.NET will write and use type names for objects and collections.

Re: Сериализация Dictionary<string, object>
От: hi_octane Беларусь  
Дата: 30.05.20 22:37
Оценка:
VD>Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?
Посмотри подойдёт ли тебе Ceras. Это практически BinaryFormatter, только делался прямыми руками. Умеет и в типы объектов, и в наследование, и в circular references.
Re: Сериализация Dictionary<string, object>
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 31.05.20 10:15
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?

https://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm
и солнце б утром не вставало, когда бы не было меня
Re: Сериализация Dictionary<string, object>
От: Kolesiki  
Дата: 01.06.20 12:36
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?


Если я правильно ошибаюсь, Newton имеет флаг "сериализовать вместе с типами". Понятно, что результат будет несколько раздутым, но... разве это так важно?
Re: Сериализация Dictionary<string, object>
От: Kolesiki  
Дата: 01.06.20 12:43
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?


О, вспомнил! Т4 шаблон? Сохраняешь в свой формат (ибо JSON тоже не идеал) и все типы корректно обрабатываются.

Я тоже столкнулся с весьма бестолковой работой Newton — получается, он сначала десериализует "нечто" в наибольший тип, а потом пытается этот тип засунуть в проперть. Это же глупо! Думаю, Т4 сериализатор уделает этот Ньютон как байкер улитку.
Re: Сериализация Dictionary<string, object>
От: karbofos42 Россия  
Дата: 01.06.20 14:46
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?


Ну, тут либо перебрать имеющиеся бинарные форматы: BSON, CBOR, MessagePack,... но вряд ли они будут отличать int от long, либо за день написать пару своих методов для сериализации/десериализации ограниченного числа типов.
Вопрос задачи и её важности. Ничего плохого в BinaryFormatter и его архивации нет. Если по факту скорость работы будет приемлема, то нечего и велосипеды строить. Те же офисные программы давно уже ушли от бинарных форматов и пришли к упакованным xml, как-то люди с этим живут
Отредактировано 01.06.2020 16:42 VladD2 . Предыдущая версия .
Re[2]: Сериализация Dictionary<string, object>
От: Ночной Смотрящий Россия  
Дата: 01.06.20 15:59
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>Вопрос задачи и её важности. Ничего плохого в BinaryFormatter и его архивации нет.


Есть. Формат в который он сериализует не детерминируется и легко может меняться от версии к версии (и менялся уже).
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re: Сериализация Dictionary<string, object>
От: #John Европа https://github.com/ichensky
Дата: 03.06.20 11:11
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?


Если object — это примитивный тип, то,
Можно хранить данные в таком формате:

key:type:value;key:type:value ...

Если тип string, то его можно хранить ввиде base64("Hello world" == SGVsbG8gd29ybGQ=)

Тогда сереализованные данные будут выглядеть как:

MQ==:int:5;Mg==:string:SGVsbG8gd29ybGQ=;MjM=:long:10 ...

Если типы, зарание известны, то их вообще можно представить как enum:
enum Types{
    @int=1,
    @string=2,
    @long=3,
}

Сериализованные данные:
MQ==:1:5;Mg==:2:SGVsbG8gd29ybGQ=;MjM=:3:10 ...
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re: Сериализация Dictionary<string, object>
От: DarthSidius  
Дата: 03.06.20 17:27
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Есть какие-то более компактные альтернативы корректно сохраняющие тип значений в object-ах?


В свое время для версии Json 6.0 писал вот такое. Сейчас может добавили поддержку.
    /// <summary>
    /// Конвертер ссылок object на простые типы или типы с дефолтным конструктором
    /// </summary>
    public sealed class ObjectRefConverter : JsonConverter
    {
        public override CanConvert(_objectType : Type) : bool { true }
        
        public override WriteJson(writer : JsonWriter, value : object, _serializer : JsonSerializer) : void
        {
            if( value == null ) {
                writer.WriteNull()
            }
            else {
                writer.WriteStartObject();
                writer.WritePropertyName(value.GetType().FullName);
                writer.WriteValue(JsonConvert.SerializeObject(value));
                writer.WriteEndObject();
            }
        }
        
        public override ReadJson(reader : JsonReader, _objectType : Type, _existingValue : object, _serializer : JsonSerializer) : object
        {
            match( reader.TokenType ) {
                | Null => null
                | StartObject => {
                    def jprops = JObject.Load(reader).Properties().ToArray();
                    JsonConvert.DeserializeObject(jprops[0].get_Value().ToString(), Type.GetType(jprops[0].Name))
                }
                | _ => throw JsonException($"Невалидный тип токена $(reader.TokenType) в поле $(reader.Path)")
            }
        }

    }


Применять:
        [JsonProperty]
        [JsonConverter(typeof(ObjectRefConverter))]
        public Asd : object { get; set }


Если чем-то поможет
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
♠♠♥♠♠♦♥
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.