Сделайте ASP.NET конвертер WCF в JSON, опустив tags «Key» и «Value»

Вот моя дилемма. Я использую службу RESTful ASP.NET, пытаясь получить функцию, чтобы вернуть строку JSON в таком формате:

{"Test1Key":"Test1Value","Test2Key":"Test2Value","Test3Key":"Test3Value"} 

Но я получаю его в этом формате:

 [{"Key":"Test1Key","Value":"Test1Value"}, {"Key":"Test2Key","Value":"Test2Value"}, {"Key":"Test3Key","Value":"Test3Value"}] 

Мой метод выглядит так:

 [OperationContract] [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] public Dictionary Test(String Token) { if (!IsAuthorized(Token)) return null; if (!IsSecure(HttpContext.Current)) return null; Dictionary testresults = new Dictionary(); testresults.Add("Test1Key", "Test1Value"); testresults.Add("Test2Key", "Test2Value"); testresults.Add("Test3Key", "Test3Value"); return testresults; } 

Есть ли способ избавиться от тегов «Key» и «Value», используя только встроенные инструменты ASP.NET? (т. е. я бы предпочел не использовать JSON.NET, если это можно избежать)

Огромное спасибо! 🙂

Класс словаря .NET не будет сериализоваться иначе, чем описанный вами. Но если вы создадите свой собственный class и закроете class словаря, вы можете переопределить методы сериализации / десериализации и быть в состоянии делать то, что вы хотите. См. Пример ниже и обратите внимание на метод GetObjectData.

  [Serializable] public class AjaxDictionary : ISerializable { private Dictionary _Dictionary; public AjaxDictionary() { _Dictionary = new Dictionary(); } public AjaxDictionary( SerializationInfo info, StreamingContext context ) { _Dictionary = new Dictionary(); } public TValue this[TKey key] { get { return _Dictionary[key]; } set { _Dictionary[key] = value; } } public void Add(TKey key, TValue value) { _Dictionary.Add(key, value); } public void GetObjectData( SerializationInfo info, StreamingContext context ) { foreach( TKey key in _Dictionary.Keys ) info.AddValue( key.ToString(), _Dictionary[key] ); } } 

Я столкнулся с этой проблемой несколько месяцев назад и разместил здесь несколько менее оптимальный краткий вопрос: настройка контракта данных WCF для надлежащего ответа JSON

Проблема, с которой я столкнулся, оказалась такой же, как и более точно заданный здесь вопрос, одним словом: в контексте WCF стандартные инструменты сериализации asp.net для словаря возвращают ARRAY, а не ключ / значение пара json ОБЪЕКТ. Я отправляю свое решение, которое работало для меня, хотя я прибегал к использованию JSON.NET (который я понимаю, что плакат пытался избежать). Тем не менее, возможно, это будет полезно кому-то.

 Function myDictionaryFunction () As Stream Implements IMywebservice.myDictionaryFunction Dim myKeyValuePairObject As Object = New Dynamic.ExpandoObject Dim myDictionary = DirectCast(myKeyValuePairObject, IDictionary(Of String, Object)) myDictionary.Add("Test1Key", "Test1Value") myDictionary.Add("Test2Key", "Test2Value") myDictionary.Add("Test3Key", "Test3Value") strJson = JsonConvert.SerializeObject(myKeyValuePairObject) Dim resultBytes As Byte() = Encoding.UTF8.GetBytes(strJson) WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain" Return New MemoryStream(resultBytes) End Function 

Результат:

 {"Test1Key":"Test1Value","Test2Key":"Test2Value","Test3Key":"Test3Value"} 

Объект expando работает как шарм. Но чтобы заставить его работать, вы должны заставить WCF возвращать простой текст, который можно было бы подумать легко, но это не так. Вы должны реализовать RawContentTypeMapper, как предлагается здесь: http://referencesource.microsoft.com/#System.ServiceModel.Web/System/ServiceModel/Channels/RawContentTypeMapper.cs … И тогда вам нужно возиться со своей сетью. config-файл примерно так:

        

Я первый, кто признал, что это решение, скорее всего, не получит никаких наgradle за элегантность. Но он работал и возвращал необработанный контент из веб-сервиса WCF, если потребуется, предоставил вам дополнительный контроль, как сериализовать вашу полезную нагрузку данных WCF. С тех пор, как это реализовано, я все больше и больше переходил на веб-интерфейс ASP.NET (что делает возrotation RESTful намного проще, чем WCF, IMO).

Немного расширившись в превосходном решении @ MarkisT, вы можете изменить конструктор сериализации, чтобы воссоздать один из этих словарей из того же JSON (таким образом, вы можете использовать AjaxDictionary как сервисный параметр) следующим образом:

 public AjaxDictionary( SerializationInfo info, StreamingContext context ) { _Dictionary = new Dictionary(); foreach (SerializationEntry kvp in info) { _Dictionary.Add((TKey)Convert.ChangeType(kvp.Name, typeof(TKey)), (TValue)Convert.ChangeType(kvp.Value, typeof(TValue))); } } 

В случае, если у кого-то есть эта проблема на стороне клиента: преобразование из этого странного {Key: “x”, Value: “y”} Array в объект {x: “y”} может выполняться в одной строке JS:

 var o = i.reduce(function (p, c, a, i) { p[c.Key] = c.Value; return p }, {}); 

с i, являющимся массивом, возвращаемым службой, и o тем, что вы действительно хотите.

с наилучшими пожеланиями

избегая «__type» в json …

в webapi.config есть несколько вариантов (посмотрите на последний):

  // To disable tracing in your application, please comment out or remove the following line of code // For more information, refer to: http://www.asp.net/web-api //config.EnableSystemDiagnosticsTracing(); // Use camel case for JSON data. config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // The setting will let json.net to save type name in the payload if the runtime type is different with the declare type. // When you post it back, json.net will deserialize the payload to the type you specified in the payload. // source: http://stackoverflow.com/questions/12858748/asp-net-webapi-posting-collection-of-subclasses //config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects; 
  • Создание веб-службы WCF с помощью запросов GET
  • Вложенность в Parallel.ForEach
  • Включить SSL для моей службы WCF
  • WCF, тип возврата интерфейса и известные типы
  • Почему разработчик должен использовать веб-службы вместо прямых подключений к db?
  • Как обрабатывать json DateTime, возвращаемые из служб данных WCF (OData)
  • Имеются ли атрибуты DataContract для WCF
  • Как использовать WSDL-файл для создания службы WCF (не звонить)
  • Зависимость впрыска wcf
  • WCF - Как увеличить размер сообщения
  • Как использовать службу WCF с Android
  • Давайте будем гением компьютера.