2017-02-20 60 views
1

Я построил веб-приложение WCF (.Net 4.5), которое отвечает на GET от http://localhost:62633/returnsdesk и возвращает список json.Возврат WCF в json также нуждается в имени для списка

[{ "Имя": "отклонить", "статус": "FULL"}, { "Name": "возвращается", "статус": "OK"}]

Однако чтобы быть лучше отформатированный JSon выглядеть:

{ "направления": [{ "destinationName": "отклонить", "статус": "FULL"}, { "destinationName": "StevesDesk",» статус ":" ОК "}] }

Я понятия не имею, как это сделать Google.

Как получить WCF для WebGet & WebMessageFormat.Json, чтобы назвать список json?

+1

Как называется заголовок, связанный с вашим вопросом? – wkl

+0

Вы правы в названии вопросов. Я исправлю это прямо сейчас. Не знаю, откуда это взялось. Благодарю. – Steve

+1

@Will No.Не отредактировано вручную. '[{" Name ":" reject "," status ":" FULL "}, {" Name ":" returns "," status ":" OK "}]' - строка WCF возвращается. Байт за байтом. но проблема в том, что в списке нет имени. – Steve

ответ

0

Это действительно относится к @ user18925 38

Возьмите тот тип, который был сериализации и возвращает WCF в списке (List<Desk>) и завернуть, что в другом типе, например:

[DataContract] 
    public class retDesks { [DataMember] public List<Desk> destinations; } 

Теперь WCF возвращает нужное имя:

{"destination": [{"ID": 1, "destinationName": "reject", "status": "FULL"}, {"ID": 2, "destinationName": "StevesDesk", "status ":" ОК "}]}

Но вы также заметите, что объект Json Desk также включает в себя атрибут ID. До ID был скрыт с вывода по определению Desk, потому что ID не был украшен [DataMember].

Теперь, однако, украшения на Desk не имеют значения, потому что весь тип Desk выставлен, так как retDesks имеет [DataMember] List<Desk>.

Итак, как вы справляетесь с этим? Самым любимым быстро предложение, использовать Linq, чтобы отфильтровать свойства List<Desks> как в:

var d1 = _desks.Select(e => new { e.destinationName, e.status }); 

Плохие новости здесь d1 список анонимного типа. Это неприемлемо для определения типа retDesks, который содержит List<Desks>.

Итак ... создайте третий тип public deskRet [ public string destinationName; public string status; } и установите этот тип как список между выводом Linq и экземпляром возвращаемого типа retDesks.

public class Desk { public int ID; public string destinationName; public string status; } 

public class retDesks { [DataMember] public List<deskRet> destinations; } 

public class deskRet { public string destinationName; public string status; } 

... 

List<deskRet> d1 = _desks.Select(e => 
    new deskRet{ destinationName=e.destinationName, status=e.status } 
    ).ToList<deskRet>(); // maybe I'm working to hard to guarantee the type. But I'm okay with that 
return(new retDesks{ destinations=d1 }; 

В конце дня у вас есть spec'ed выход:

{ "направления": [{ "destinationName": "отклонять", "статус": "FULL"} { "destinationName": "StevesDesk", "статус": "OK"}]}

Но в следующий раз рассмотрит рамку третьей стороны, как Json.NET. Или, может быть, пользовательский Json Serialzer с использованием. Net WCF Framework.

2

Я предполагаю, что у вас есть метод, украшенный

[WebInvoke(Method = "GET", 
     RequestFormat = WebMessageFormat.Json, 
     ResponseFormat = WebMessageFormat.Json, 
     UriTemplate = "returnsDesk")] 
[WebGet(ResponseFormat = WebMessageFormat.Json)] 

возвращающая List<Desk>.

public List<Desk> GetDesks() 
{ 

Вы должны вернуть новый класс DeskList с [DataMember] украшенной destinations собственности, определяется как List<Desk>, содержащий такой список, вместо этого.

+0

Все ваши предположения верны. Это ПОЛУЧЕНИЕ. Я даже попробовал '\t \t [return: MessageParameter (Name =" balbal ")]' decoration (не работал здесь, но я бы хотел, чтобы он это сделал. Возможность программной настройки этого атрибута была бы приятной). Остальное, что вы говорите, имеет смысл, и я попробую это позже и вернусь к вам здесь. Каким-то образом я просто подумал, что это произошло только для списков , и был удивлен, увидев, что это не так. – Steve

+1

@ user1892539 Работал как шарм, но, может быть, у вас есть подсказка. У моего внутреннего класса «Стол» есть атрибуты, которые раньше не были подвергнуты json, поскольку они не имели украшения [DataMember]. Конечно, теперь все эти атрибуты включены в выход json, хотя сам класс «Desk» по-прежнему имеет только «destinationName» и «status», украшенные [DataMember]. Я, честно говоря, не видел этого. – Steve

+0

Похоже, вы спрашиваете об этом [вопрос] (http://stackoverflow.com/questions/27092802/serialize-object-into-json-but-only-include-properties-with-the-datamember-att), aren Не так ли? –

0

кредиты для LongNameContractResolver пойти Bryon Rogers

Привет, вы можете использовать NewtonSoft.Json ссылка на сериализации и десериализации объектов


Посмотрите на код ниже, чтобы ответить на ваш вопрос

using Newtonsoft.Json; 
using Newtonsoft.Json.Serialization; 
using System; 
using System.Collections.Generic; 

namespace JsonNamedList 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      //Destinations object 
      var destinations = MockGetDestinations(); 
      //Destinations object as Json string, use the LongNameContractResolver to ignore the Json Property Name 
      var strDestinationsJson = LongNameContractResolver.Serialize(destinations, true); 
      //Print the destinations Json to output 
      Console.WriteLine(strDestinationsJson); 
      //Stop closing the console window 
      Console.ReadKey(); 
     } 

     static Destinations MockGetDestinations() 
     { 
      //[{"Name":"reject","status":"FULL"},{"Name":"returns","status":"OK"}] 
      var apiResponse = "[{'Name':'reject','status':'FULL'},{ 'Name':'returns','status':'OK'}]".Replace("'", "\""); 
      var wrappedApiResponse = WrapIntoDestinations(apiResponse); 
      //destinations as object 
      var destinations = JsonConvert.DeserializeObject<Destinations>(wrappedApiResponse); 

      return destinations; 
     } 

     static string WrapIntoDestinations(string apiResponse) => $"{{'destinations': {apiResponse} }}".Replace("'", "\""); 
    } 

    public class Destination 
    { 
     [JsonProperty(PropertyName = "Name")] 
     public string destinationName { get; set; } 

     [JsonProperty(PropertyName = "status")] 
     public string status { get; set; } 
    } 
    public class Destinations 
    { 
     [JsonProperty(PropertyName = "destinations")] 
     public IEnumerable<Destination> destinations { get; set; } 
    } 
    public class LongNameContractResolver : DefaultContractResolver 
    { 
     protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
     { 
      // Let the base class create all the JsonProperties 
      // using the short names 
      IList<JsonProperty> list = base.CreateProperties(type, memberSerialization); 

      // Now inspect each property and replace the 
      // short name with the real property name 
      foreach (JsonProperty prop in list) 
      { 
       prop.PropertyName = prop.UnderlyingName; 
      } 

      return list; 
     } 
     public static string Serialize(object obj, bool useLongNames) 
     { 
      JsonSerializerSettings settings = new JsonSerializerSettings(); 
      settings.Formatting = Formatting.Indented; 
      if (useLongNames) 
      { 
       settings.ContractResolver = new LongNameContractResolver(); 
      } 

      return JsonConvert.SerializeObject(obj, settings); 
     } 
    } 
} 

Это дает следующий результат (Json String) enter image description here