У меня есть дерево объектов, которое я сериализую в JSON с DataContractJsonSerializer
. Dictionary<TKey, TValue>
сериализуется, но мне не нравится разметка - элементы не отображаются следующим образом:
{key1:value, key2:value2}
а скорее как массив сериализованных KeyValuePair<TKey, TValue>
объектов:
[{
"__type":"KeyValuePairOfstringanyType:#System.Collections.Generic",
"key":"key1",
"value":"value1"
},
{
"__type":"KeyValuePairOfstringanyType:#System.Collections.Generic",
"key":"key2",
"value":"value2"
}]
Ужасно, не правда ли?
Итак, я избегаю этого, обертывая общий словарь в пользовательский объект, реализующий ISerializable
, и реализую свою собственную сериализацию в методе GetObjectData
(и занимает всего 3 строки).
Теперь проблема - я не могу сделать свой класс из Dictionary<TKey, TValue>
, поэтому я реализую всю логику (Add
, Clear
и т.д.) в своем пользовательском классе, применяя к закрытому Dictionary<TKey, TValue>
поле. Наследование было бы предпочтительнее, поскольку у меня будут все общие функции словаря в моем распоряжении при использовании моего пользовательского объекта.
Проблема с наследованием заключается в том, что Dictionary<TKey, TValue>
реализует ISerializable
самостоятельно, а DataContractJsonSerializer
, похоже, предпочитает эту реализацию, даже если я реализую ISerializable
явно из моего пользовательского класса, например:
public class MyClass : Dictionary<string, object>, ISerializable
{
public override void GetObjectData(SerializationInfo info,
StreamingContext context)
}
Я был действительно удивлен, что это возможно, поскольку это позволяет мне реализовать один и тот же интерфейс дважды, не имея явно возможности использовать явную реализацию интерфейса, поэтому я более подробно проанализировал ситуацию в сообщении в блоге о реализации нескольких интерфейсов
Итак, согласно проведенным там экспериментам, сериализатор должен называть мою реализацию ISerializable, независимо от того, какой тип литья используется внутри -
((ISerializable)((Dictionary<,>)obj)).GetObjectData(...)
или
((ISerializable)obj).GetObjectData(...)
но это, по-видимому, не происходит, как я вижу в полученном JSON, который все еще вызывает сериализатор KeyValuePair<TKey, TValue>
. Что может случиться, что мне не хватает?
Обновление: Ответы и комментарии, которые я получаю до сих пор, в значительной степени только предполагают обходные пути. Я отметил, однако, что у меня есть обходное решение, которое работает очень хорошо, поэтому, задав этот вопрос, у меня есть две цели:
-
В конце концов заставьте его работать с оригинальным дизайном - и я не собираюсь менять логику сериализации только для этого, в нем много кода и логики.
-
Чтобы не понимать тайну, почему не является
DataContractJsonSerializer
с использованием моего кода сериализации - как видно из сообщения в блоге, которое я упоминал, я сделал всевозможные эксперименты с реализацией интерфейса и наследованием, и я был уверенный, что я улавливаю все входы и выходы процесса, поэтому я обеспокоен тем, что не понял, что происходит в этом случае