Pytanie Jaki jest najlepszy sposób serializacji jSON .NET DataTable w WCF?


Kiedy konfiguruję WCF, aby korzystać z serializacji jSON, i uwzględniam DataTable w jednej z moich Kontencji danych, to serializuje ona DataTable do XML przed serializacją całego DataContract do jSON. Chcę, aby DataTable były serializowane jako jSON, a nie XML.

Moje pytania to:

  1. Dlaczego najpierw serializuje DataTable do XML?
  2. Jak mogę go zamiast tego przekształcić do JSON?

14
2017-07-29 15:50


pochodzenie


Witamy w S.O. Co próbowaliście, żeby serializować z Jsonem? - Daniele Armanasco
Rozważ to i skonwertuj dane do JSON stackoverflow.com/questions/17398019/... - Ali Umair


Odpowiedzi:


  1. DataTable jest czystym konstruktem .NET, który nie może być (łatwo) przedstawiony bezstratnie przez JSON. DataTables zawiera wiele dodatkowych informacji, których JSON nie może przechowywać: klucze podstawowe, funkcje autoincs, dopuszcza wartości null, podpis, typ danych, indeksy itp. Serializacja do formatu XML / binarnego to jedyne sposoby serializowania tabeli DataTable przez .NET. Ta serializowana XML DataTable jest następnie serializowana do JSON.

  2. Posługiwać się JSON.NET lub FastJSON przekształcić DataTable w czystą, zgodną z JSON wersją DataTable, która może być używana przez dowolnego klienta JSON, a nie tylko klientów WCF .NET. Utracisz wszystkie właściwości niestandardowe DataTable wymienione w punkcie (1) powyżej i uzyskasz tylko parę JSON nazwy / wartości pola. Przechowywanie w ten sposób jest nieefektywne z powodu powielania nazw pól w każdym rzędzie.

Nie używaj DataTable w DataContract. Jeśli chcesz korzystać z DataTable, a Twoi klienci zawsze będą .NET, serializować DataTable do tablicy bajtów poprzez szeregowanie binarne, a następnie opcjonalnie skompresować wynikowy serializowany strumień bajtów. Ujawnij tablicę bajtów w swoim DataContract. Zapewni to wydajną, w pełni bezstratną wersję DataTable po stronie klienta (po dekompresji i deserializacji binarnej), a nie rozwodnioną wersję JSON DataTable (oferowaną przez (2)) ...


13
2017-07-29 18:06



Świetne odpowiedzi. Dziękuję Ci. Moi klienci to nie wszystko .NET i szybko odkryłem wspomniane nieefektywności. Spróbuję zmodyfikować to podejście, aby nie musiałem podawać nazw kolumn / pól w każdym wierszu. - rhyno
Wiem, że jest to stary wątek, ale fastjson wspiera serializowanie / deserializację datowaną z wersji 1.7.7, która została wydana przed czerwcem 2011 roku. Format xml jest nieefektywny, zawiera niewygodny znacznik dla każdego wiersza AND. - Crisim Il Numenoreano
@Keith Blows, a co z serializacją listy DataTables? Jak sugerujesz to zrobić? - Xegara


Spróbuj tego:

public string ConvertDataTabletoString(System.Data.DataTable dt)
{
    System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
    Dictionary<string, object> row;
    foreach (System.Data.DataRow dr in dt.Rows)
    {
        row = new Dictionary<string, object>();
        foreach (System.Data.DataColumn col in dt.Columns)
        {
            row.Add(col.ColumnName, dr[col]);
        }
        rows.Add(row);
    }
    return serializer.Serialize(rows);
}

5
2018-03-07 11:04





Miałem ten sam problem, moja usługa wcf nie formatowała json poprawnie podczas konwersji z Dataset do Json. Mam to działa przy użyciu następującego rozwiązania:

using System.ServiceModel.Channels;
using System.ServiceModel.Web;

dsData to mój zbiór danych

string json = Newtonsoft.Json.JsonConvert.SerializeObject(dsData);
return WebOperationContext.Current.CreateTextResponse(json, "application/json;charset=utf-8", System.Text.Encoding.UTF8);

a "Message" będzie typem zwracanym.


3
2017-12-24 04:09



Ta odpowiedź naprawdę uratowała mi życie :) Porzuciłem poszukiwanie prostej metody zwracania DataTable z db do JSON bez deklarowanie obiektów jawnie dla każdej tabeli / procedury. Mój błąd polegał na tym, że mój OperationContract zwracał serializowany json po prostu jako string. W ten sposób wymagało to na przykład użycia JSON.parse Strona klienta. Zmienianie typu zwrotu na System.ServiceModel.Channels.Message i za pomocą WebOperationContext.Current.CreateTextResponse(string) jak pokazane powyżej działa świetnie! :) - Skipper
Nigdy nie myślałem, że możesz zrobić coś takiego z WCF WS - ustawiając odpowiedź zamiast po prostu powracać int/string/class/List<T> etc - Skipper


Zgodnie z wykresem na jego stronie głównej, Json.NET jest naprawdę jedyną opcją - możesz szybko ją pobrać NuGet. Na szczęście jest to świetna biblioteka i bardzo łatwa w użyciu.

string json = JsonConvert.SerializeObject(myDataSet, new DataSetConverter());

Zauważ, że Rich Strahl ma świetny post z większą ilością szczegółów, a także zawiera niestandardową pracę, której używał JavaScriptSerializer z (raczej rozległymi) niestandardowymi konwerterami dla porównania.


2
2017-07-29 16:12



To zadziałało, ale szybko zdałem sobie sprawę, że nazwy kolumn i danych są zawarte w KAŻDYM rzędzie, co czyni go bardzo nieefektywnym, o czym wspomniał Keith. Mam zamiar spróbować zmodyfikować DataTableConverter i DataRowConverter tak, że nie będę powtarzać wszystkich tych nazw kolumn / pól. - rhyno
@Rhyno jakie było Twoje rozwiązanie końcowe, aby nie powtarzać wszystkich nazw kolumn / pól? Mam pomysł, co zamierzam zrobić, ale jeśli już to zrobiłeś, zaoszczędziłoby to trochę czasu. - DeadlyChambers