JsonConvert.DeserializeObject и оболочка "d" в WCF - PullRequest
3 голосов
/ 26 октября 2009

По умолчанию служба WCF переносит ответ JSON в оболочку "d", и там я обнаружил проблему с ее анализом.

Если я анализирую с JsonConvert.DeserializeObject (response) , где response

"{\"d\":\"{\"a0b70d2f-7fe4-4aa2-b600-066201eab82d\":\"Thelma\",\"d56d4d4f-6029-40df-a23b-de27617a1e43\":\"Louise\"}\"}"

У меня ошибка:

After parsing a value an unexpected character was encoutered: a. Line 1, position 9.

Если я поменяю ответ на

"{\"a0b70d2f-7fe4-4aa2-b600-066201eab82d\":\"Thelma\",\"d56d4d4f-6029-40df-a23b-de27617a1e43\":\"Louise\"}"

У меня все получилось.

Так как же проанализировать эти завернутые в "d" ответы JSON от служб WCF? Есть ли лучший способ разобрать JSON?

Ответы [ 7 ]

11 голосов
/ 03 июня 2011

Я предполагаю, что вы используете <enableWebScript/> в своей конфигурации поведения, замените его на <webHttp defaultOutgoingResponseFormat="Json"/>, и вы получите хороший и чистый json, без "d" и без "__type"

2 голосов
/ 27 октября 2009

Похоже, что вы используете поведение enableWebScript в своем webHttpBinding. Вы, вероятно, должны использовать вместо этого поведение webHttp - это дает вам «чистый» JSON вместо JSON клиента ASP.NET AJAX.

1 голос
/ 22 апреля 2015

Возьмите свой json и вставьте его в онлайн-генератор классов, например http://httputility.net/json-to-csharp-vb-typescript-class.aspx. Он предоставит вам код для десериализации этого объекта json, например так (пример VB):

Public Class MyClass
     Public Property D As String
End Class

Вставьте это в ваш проект и десериализуйте JSON в этот объект. Свойство D теперь представляет собой строку, содержащую развернутый json, который вам потребуется во второй раз десериализовать в ваш последний получающий объект. Если вы не уверены в классе, который вам понадобится обработать, вставьте строку в D в тот же генератор онлайн-классов, и у вас будет код, необходимый для создания типа для получения объекта!

0 голосов
/ 09 марта 2011

Может быть, это поможет.

Услуга:

namespace Application.Service
{
        [ServiceBehavior(UseSynchronizationContext = false,
        ConcurrencyMode = ConcurrencyMode.Multiple,
        InstanceContextMode = InstanceContextMode.PerCall),
        AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
        public class VendorService : IVendorService
        {
          public List<Vendor> RetrieveMultiple(int start, int limit, string sort, string dir)
          {
             //I don't do any manual serialization
             return new Vendor();
          }
        }
}

Контракт:

    [ServiceContract(Namespace = "Application.Service.Contracts")]            
    public interface IVendorService
    {
       [OperationContract]
       [WebInvoke(ResponseFormat=WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        List<Vendor> RetrieveMultiple(int start, int limit, string sort, string dir);
     }

В моем файле Svc есть только эта строка:

<%@ ServiceHost Service="Application.Service.VendorService" %>

Web.config

<system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <behaviors>
      <endpointBehaviors>
        <behavior name="jsonBehavior">
          <enableWebScript />
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="DefaultServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

  <service behaviorConfiguration="DefaultServiceBehavior" name="Application.Service.VendorService">
    <endpoint behaviorConfiguration="jsonBehavior" address="" binding="webHttpBinding" contract="Application.Service.Contracts.IVendor" />
  </service>
0 голосов
/ 07 марта 2011

У вас может быть класс-оболочка десериализации, у которого есть одно свойство с именем "d". После того, как вы успешно десериализовали его, получите значение из свойства d.

0 голосов
/ 07 марта 2011

Если вы переключаетесь на WebHttpBehavior и по-прежнему получаете сообщение об ошибке об элементах тела без переноса, вручную установите стиль тела методов, с которыми вы работаете, на Wrapped. Сделай это так:

[OperationContract (BodyStyle = WebMessageBodyStyle.Wrapped, ...)] строка DoSomething (...)

Надеюсь, это поможет!

0 голосов
/ 27 октября 2009

Теперь я избавился от оболочки d с помощью Regex.Replace и исправил ответ JSON с правильной структурой

{\"Guid\":\"a0b70d2f-7fe4-4aa2-b600-066201eab82d\",\"Name\":\"Thelma\"}
{\"Guid\":\"d56d4d4f-6029-40df-a23b-de27617a1e43\",\"Name\":\"Lousie\"}\"}

Я также создаю класс с Guid и Name, определенными в нем как строка.

Затем попробуйте десериализовать его с помощью

List<myStruct> o = JsonConvert.DeserializeObject<List<myStruct>>(response);

Но я получаю ошибку

Expected a JsonObjectContract or JsonDictionaryContract for type 'System.Collections.Generic.List`1[mynamespace.myStruct]', got 'Newtonsoft.Json.Serialization.JsonArrayContract'.

Где трюк?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...