wcf десериализует перечисление как строку

Я пытаюсь использовать веб-службу RESTful с помощью WCF. У меня нет контроля над форматом веб-службы, поэтому я должен найти несколько обходных путей здесь и там. Однако одна серьезная проблема, которую я не могу решить, - это как заставить WCF десериализовать перечисление как строку.

Это мой код (имена, очевидно, изменены):

[DataContract]
public enum Foo
{
    [EnumMember( Value = "bar" )]
    Bar,

    [EnumMember( Value = "baz" )]
    Baz
}

[DataContract]
public class UNameIt
{
    [DataMember( Name = "id" )]
    public long Id { get; private set; }

    [DataMember( Name = "name" )]
    public string Name { get; private set; }

    [DataMember( Name = "foo" )]
    public Foo Foo { get; private set; }
}

И это возвращенные данные, которые не прошли десериализацию:

{
     "id":123456,
     "name":"John Doe",
     "foo":"bar"
}

Наконец, выброшено исключение:

Произошла ошибка десериализации объекта типа Service.Foo. Значение bar не может быть проанализировано как тип Int64.

Я не хочу переключаться на использование XmlSerializer, потому что, среди множества других недостатков, он не позволяет мне иметь частные установщики свойств.

Как мне заставить WCF (или, ну, DataContractSerializer) обрабатывать мое перечисление как строковые значения?

РЕДАКТИРОВАТЬ: это кажется невозможным, и поведение таково, как задумано. Спасибо, Microsoft, за то, что не предоставили нам возможности прибегать к хакерским атакам. Делать это так, как предлагает Сомори, кажется, единственный способ получить перечисления строк с помощью JSON и WCF.


person Alex    schedule 22.01.2010    source источник
comment
Вы пытались создать объект UNameIt в коде и использовать DataContractSerializer для сериализации (а затем десериализации), чтобы проверить, не соответствует ли сериализация полученному сообщению?   -  person GaussZ    schedule 27.01.2010
comment
Дело в том, что сериализацию выполняю не я. Этот JSON предоставлен третьей стороной. Я ничего не могу контролировать, единственное, что я контролирую, - это десериализацию, но я думаю, что нет, потому что я не могу заставить WCF десериализовать перечисление так, как эти ребята настраивают перечисления. Я бы хотел, чтобы DataContractSerializer был более гибким.   -  person Alex    schedule 27.01.2010
comment
Да, я понимаю, что у вас нет контроля над этим, возможно, это намекнет на проблему, хотя если бы вы могли сравнить самосериализованный объект с тем, что вы получаете от третьей стороны, чтобы понять, почему сериализатору это не нравится.   -  person GaussZ    schedule 27.01.2010
comment
Старайтесь избегать использования перечислений в контрактах данных wcf, поскольку они создают тонкие проблемы обратной совместимости. См. stackoverflow.com/questions/326339/   -  person Michael Freidgeim    schedule 21.07.2013
comment
@nawfal Если вы обратите внимание, вы увидите, что этот вопрос был задан на два месяца раньше того, о котором вы говорите. Во всяком случае, это возможный дубликат этого.   -  person Alex    schedule 17.07.2014
comment
@Alex принятая политика SO заключается в том, что вы можете закрыть старый q с новым, если последний получил больше внимания / лучше сформулирован и т. д.. Тем не менее, я отозваю свой закрытый голос, потому что речь идет о DataContractSerializer в контексте WCF, а о другом - о JavascriptSerializer в ASP.NET. Я должен быть поосторожнее! :)   -  person nawfal    schedule 17.07.2014
comment
@Alex вы используете DataContractSerializer или DataContractJsonSerializer?   -  person nawfal    schedule 17.07.2014
comment
Даже не помню, это было больше четырех лет назад.   -  person Alex    schedule 17.07.2014


Ответы (3)


Это может быть глупый вопрос.

Что произойдет, если вы это сделаете

[DataMember( Name = "foo" )]
private string foo { get; private set; }

public Foo Foo 
{ 
  get 
  {
    return Foo.Parse(foo);
  }
}

?

person Simon Gill    schedule 27.01.2010
comment
Я уже пробовал это, и это работает, но это взлом, и если его можно избежать, я хочу избежать этого. - person Alex; 28.01.2010
comment
На самом деле, похоже, это единственный способ сделать это, см. stackoverflow .com / questions / 794838 / - person Alex; 28.01.2010
comment
Вам также понадобится сеттер, не так ли? - person Juan Mendes; 29.04.2014
comment
Приносим извинения за слишком поздний ответ, @JuanMendes, но нет, не для конкретного случая использования, который у меня был. Десериализатор будет записывать только в свойство foo, а поскольку мне нужна была только десериализация, мне нужно было только прочитать значение Foo, а не устанавливать его. - person Alex; 21.03.2018

Я знаю, что это старый пост, но я думаю, что о нем стоит упомянуть.

Я получил аналогичную ошибку, когда десериализация строки json завершилась неудачно, что, похоже, привело к десериализации на неправильные типы.

Для меня исправление заключалось в том, чтобы просто URL-адрес закодировать строку json перед ее отправкой на сервер. Простая, но легкая ошибка.

HttpUtility.UrlEncode(JSONInstruction) /*remember to encode the string*/
person MHALottering    schedule 01.07.2011

Э ..? Разве перечисления не целые? Исключение действительно. Не знаю, поможет ли это: http://msdn.microsoft.com/en-us/library/aa347875.aspx

person Community    schedule 23.01.2010
comment
Нет, это не так. Вы сами читали эту статью? Вот интересный отрывок: обычно контракт данных включает имена членов перечисления, а не числовые значения. Однако при использовании модели контракта данных, если принимающей стороной является клиент WCF, в экспортированной схеме сохраняются числовые значения. Проблема в том, что я являюсь клиентом WCF. Однако сервер использует перечисления строк. Я немного в тупике ... - person Alex; 23.01.2010
comment
Мог ли серверный код ошибаться? Можно ли в этом случае использовать структуру данных? - person ; 23.01.2010
comment
Сервер не является службой WCF, я думаю, он работает на Python. Я не могу изменить то, как они что-то делают, я просто потребитель в этом сценарии, и я должен действовать по их правилам. - person Alex; 27.01.2010