Mass Transit не может десериализовать коллекции только с одним элементом

У меня есть интерфейс сообщения Mass Transit, подобный этому:

public interface IPerson
{
    ICollection<PersonalName> Names { get; }
}

public class PersonalName
{
    public string FamilyName { get; set; }
    public string GivenName { get; set; }
    public string SecondName { get; set; }
    public string Use { get; set; }
}

И это работает для сериализации и десериализации сообщения с использованием JsonMessageSerializer. Я также могу сериализовать сообщение, используя XmlMessageSerializer, и результат будет выглядеть примерно так:

<person>
    <names>
        <familyName>Simpson</familyName>
        <givenName>Homer</givenName>
        <secondName>Jay</secondName>
        <use>Official</use>
    </names>
    <names>
        <givenName>Homie</givenName>
        <use>Nickname</use>
    </names>
</person>

И я могу десериализовать только его, если коллекция пуста или содержит более одного элемента. Однако, если коллекция содержит ровно один элемент, при ее десериализации я получаю следующую ошибку:

Невозможно десериализовать текущий объект JSON (например, {"name":"value"}) в тип 'System.Collections.Generic.ICollection`1[MyNs.PersonalName]', поскольку для правильной десериализации этого типа требуется массив JSON (например, [1,2,3]).

Чтобы исправить эту ошибку, либо измените JSON на массив JSON (например, [1,2,3]), либо измените десериализованный тип, чтобы он был обычным типом .NET (например, не примитивный тип, такой как целое число, не тип коллекции, такой как массив или List<T>), который может быть десериализован из объекта JSON. JsonObjectAttribute также можно добавить к типу, чтобы заставить его десериализоваться из объекта JSON.

Путь 'person.names.familyName'.

Я могу исправить это, используя массив или List<T>, но мне бы очень хотелось этого избежать. Есть ли способ заставить Mass Transit XmlMessageSerializer десериализовать типы ICollection<T>? Поскольку Mass Transit использует Json.NET для сериализации под капотом (даже для XML), я надеюсь, что есть какой-то способ аннотировать тип, чтобы он мог принимать ICollection<T>.


person p.s.w.g    schedule 21.04.2014    source источник
comment
Можно ли использовать IList<T> вместо ICollection<T>? Если нет, откройте вопрос на GitHub (github.com/MassTransit/MassTransit), и, возможно, мы может сделать эту работу.   -  person Travis    schedule 21.04.2014
comment
А так как ICollection<T> реализуется IList<T>, скорее всего, он просто привязывает правильный сериализатор к ICollection<T>, так что, скорее всего, это легко исправить.   -  person Travis    schedule 21.04.2014
comment
@Travis Я разрабатываю библиотеку сообщений, в которой я хотел бы семантически идентифицировать эту коллекцию как «сумку», где порядок или уникальность не важны. В других частях библиотеки, где важен порядок, я использую IList, а там, где важна уникальность, я использую ISet. Так что я могу использовать IList, но это будет означать принятие семантики, присущей IList, где это неуместно. Я надеюсь, что в этом есть смысл.   -  person p.s.w.g    schedule 21.04.2014


Ответы (1)


Вместо того, чтобы пытаться десериализовать:

{"FamilyName":"Smith","GivenName":"John"}

вам нужно передать массив для десериализации:

[{"FamilyName":"Smith","GivenName":"John"}]
person pkr    schedule 21.04.2014
comment
Mass Transit использует Json.NET для сериализации XML, см. пример в моем обновлении. - person p.s.w.g; 21.04.2014