Bagaimana menghapus k__BackingField dari json saat Deserialize

104

Saya mendapatkan k_BackingField di json saya yang dikembalikan setelah membuat serial file xml ke objek .net c #.

Saya telah menambahkan DataContract dan atribut DataMember ke objek .net c # tapi kemudian saya tidak mendapatkan apa-apa di json, klien akhir.

[XmlRoot("person")]
[Serializable]
public class LinkedIn
{
    [XmlElement("id")]
    public string ID { get; set; }

    [XmlElement("industry")]
    public string Industry { get; set; }

    [XmlElement("first-name")]
    public string FirstName { get; set; }

    [XmlElement("last-name")]
    public string LastName { get; set; }
    [XmlElement("headline")]
}

Contoh json yang dikembalikan:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"
Mengisi Tumpukan adalah Apa yang Saya LAKUKAN
sumber

Jawaban:

45

Sintaks Properti Otomatis sebenarnya tidak disarankan jika kelas dapat digunakan dalam serialisasi. Alasannya adalah backing field dihasilkan oleh compiler yang bisa berbeda setiap kali kode dikompilasi. Hal ini dapat menyebabkan masalah ketidakcocokan meskipun tidak ada perubahan yang dibuat pada kelas (cukup kompilasi ulang kode).

Saya pikir menerapkan atribut DataMember akan memperbaiki masalah dalam kasus ini. Tetapi saya akan merekomendasikan untuk menggunakan sintaks properti penuh, jika kelas perlu digunakan dalam serialisasi.

jags
sumber
Lol, menerapkan versi panjang dan menyetel bidang pribadi ke klien. Home: Object _fName: "Storefront" _headline: "CEO at StorefrontDoors.NET" _id: "" _industry: ""
Filling The Stack is What I DO
21
menambahkan datacontract ke bagian atas kelas dan anggota data ke setiap properti yang saya minati bekerja.
Filling The Stack is What I DO
3
@ AlumCloud.Com +1 untuk [DataContract] dan [DataMember]. Jangan lupa untuk menambahkan: System.Runtime.Serialization
Ian Newland
109

Hapus [Serializable]dari kelas Anda

Safaa Elgendi
sumber
2
Sekarang saya bertanya-tanya mengapa saya pikir saya membutuhkan [Serializable] di tempat pertama. Serialisasi Xml saya berfungsi tanpa dan JSON bekerja tanpa itu.
Rhyous
11
Ini tidak bekerja dengan Layanan WCF. Saat mengembalikan payload menggunakan layanan RESTful, ini tidak menghasilkan data apa pun jika Anda menghapus [Serializable]. Tambahkan System.Runtime.Serialization dan gunakan [DataContract] untuk kelas, [DataMember] untuk properti.
Ian Newland
Jawaban DAN komentar Ian ini tampaknya mencakup kedua kasus tersebut. Untuk WCF atau tidak ke WCF, itulah pertanyaannya.
granadaCoder
1
@Rhyous - di Web API Anda tidak memerlukan [Serializable], karena Web API diatur dengan asumsi Anda akan membuat serial dan mengembalikan objek Anda (karena pada dasarnya itu adalah keseluruhan ide) - di aplikasi C # lain Anda biasanya perlu Serializable untuk membedakan objek yang dapat diserial
Jon Story
Terima kasih, saya terjebak [Serializable], jadi menambahkan bidang dukungan membantu.
ohmusama
59

Serializer WebApi default akan menambahkan sintaks "__BackingField:" ke c # auto-properties. Tambahkan ini ke WebConfig Anda di App_Start untuk mendapatkan json yang tampak lebih bersih yang mungkin Anda cari.

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Dan
sumber
3
Ini memperbaiki masalah. Menurut saya, properti mobil bersih. Menggunakan bidang pendukung di mana-mana tampak bodoh. dan menimbulkan banyak kekacauan dan terkadang kebingungan.
Romesh D. Niriella
Ini berhasil untuk saya. Dalam kasus saya, saya memiliki kelas yang sudah digunakan oleh layanan web WCF dan ASMX, jadi saya tidak bisa mengubahnya untuk proyek WebAPI baru saya.
samiup
4
Pertanyaannya adalah mengapa serializer WebApi bumi akan menambahkan "__BackingField:" secara default?
Teoman shipahi
solusi yang bagus. dalam kasus saya, saya perlu menggunakan [Serializable] simpan ke memcache. Diperlukan serializable.
Bình Nguyễn Quang
2
Apa yang akan saya lakukan tanpa StackOverflow? Terima kasih.
camainc
35

Kami memiliki beberapa objek yang ditandai [Serializable]sehingga mereka dapat diserialkan menggunakan metode tradisional, tetapi kami harus memiliki serialisasi yang rapi di JSON untuk digunakan dengan API Web. Pengaturan IgnoreSerializableAttributeke trueakan menghentikan Newtonsoft.Json berperilaku seperti penyerial Microsoft dan sebaliknya itu hanya akan membuat serial properti publik.

TLDR: Tambahkan ini ke WebApiConfig.cs:

((Newtonsoft.Json.Serialization.DefaultContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver).IgnoreSerializableAttribute = true;

Moderator: Daripada menghapus jawaban yang sangat bagus untuk pertanyaan yang telah diajukan beberapa kali, harap hapus pertanyaan duplikat. Ini adalah jawaban yang valid untuk pertanyaan yang valid.

Richard
sumber
3
Ini harus menjadi jawaban yang benar. Menghapus Serialization atau menggunakan datacontract dan atribut datamember tidak selalu merupakan solusi yang tepat.
Houssam Hamdan
Banyak dari kami yang tidak, termasuk OP, menggunakan Webapi atau MVVM atau apa pun yang kalian bicarakan. Apa itu app_start dan webapiconfig ketika saya memiliki layanan WCF sabun normal dengan service.svc?
Christian
10

Sederhana Cara Mudah dan Layak untuk mengekspos data Kita perlu mengekspos data dalam objek ke format yang mudah dibaca dan konsisten


Pertama hapus [Serializable]

    [Serializable]

sekarang tambahkan [DataContract] di kelas dan [DataMember] untuk properti seperti contoh di bawah ini

[DataContract]
public class UserDiscretion : UserReport
{
    [DataMember]
    public String DiscretionCode { get; set; }
    public String DiscretionDescription { get; set; }
}

Semoga bantuan ini
Terima kasih.

Nagendra Upwanshi
sumber
1
Jika menggunakan Web API, tidak perlu menambahkan atribut DataContract dan DataMember sama sekali - cukup kembalikan objek dan itu akan diserialkan secara otomatis.
Jon Story
Jika ada yang memulai pengembangan dari awal maka akan sangat bagus untuk menggunakan API Web yang akan menyediakan tipe pengembalian Objek tidak akan memerlukan semua jenis tipe casting untuk mengekspos ke klien. Tapi untuk pertanyaan @ AlumCloud.com, jika dia dalam aplikasi yang sudah ada maka solusi untuk masalahnya adalah dengan terlebih dahulu menghapus [Serializable] kemudian menambahkan [DataContract] di kelas dan [DataMember] untuk properti seperti di bawah ini seperti yang disarankan
Nagendra Upwanshi
1
Ini menambahkan sejumlah besar "gangguan" ke kelas Anda dan pada dasarnya tidak perlu (lihat semua komentar lainnya). Jika seseorang merasa perlu untuk benar-benar melakukan ini, bagaimanapun, saya akan merekomendasikan menggunakan sesuatu seperti PostSharp untuk menambahkan kode untuk Anda selama kompilasi sehingga tidak mengacaukan kelas Anda dengan semua atribut tersebut.
camainc
7

Beberapa opsi:

  1. Hapus [Serializable]dari model

  2. Tambahkan [DataContract]dan [DataMember]ke model Anda bersama dengan [Serializable]

  3. Tambahkan baris di bawah ini ke App_Start/WebApiConfig.cs

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
Jayaprakash Muthugopal
sumber
3

Solusi lain yang dapat membantu dalam kasus JSON.NET. Ini mungkin cukup untuk menandai kelas dengan atribut [Newtonsoft.Json.JsonObject].

Saya bekerja dengan kelas cs yang dibangun dari xsd dan menambahkan beberapa properti menggunakan kelas parsial. Setelah serialisasi json, properti ini ditandai dengan k_BackingField. Pengaturan JsonFormatter yang disebutkan dalam jawaban lain juga membantu, tetapi yang lebih sederhana adalah menandai kelas sebagian dengan atribut [JsonObject].

sarh
sumber
2

Saya menggunakan DataContractJsonSerializerdengan kelas dari majelis lain yang memiliki Serializableatribut. Keluarannya berisi "k__BackingField". Menghapus Serializableatribut (di perakitan lain) memperbaiki ini. Tidak yakin kenapa.

Little Endian
sumber
0

Dengan asumsi Anda melihat masalah ini di dalam proyek MVC Anda, menurut saya cukup mudah untuk mengganti penggunaan @ Html.JsonData. Berikut ini cuplikan kode yang telah berhasil untuk saya di masa lalu:

<input type="hidden" id="Model" value="@Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model))" />

Tidak seanggun, tapi sederhana dalam keadaan darurat.

Ryan Roark
sumber
0

Saya mengalami masalah ini ketika saya memiliki properti referensi mandiri di kelas saya seperti;

class Person {
 List<Person> Friends { get; set;}
}

Dan hasilnya, orang itu berteman dengan dirinya sendiri. Saya hanya memastikan tidak ada objek referensi mandiri di set hasil saya. Semoga ini membantu.

Teoman shipahi
sumber
0

Saya harus menggunakan atribut [Serializable], jadi menghapusnya bukanlah pilihan.

XmlSerializer mengabaikan [XmlAttribute] di WebApi

Resolusi di atas menyelesaikannya untuk saya.

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
JanBorup
sumber
0

dalam kasus saya kesalahan ini adalah untuk Versi Newtonsoft.Json, server mencari versi 6.0.0 dan saya memiliki versi 11.0, jadi saya harus menginstal versi 6.0.0

Andres Guillen
sumber
-2

Teman, jangan nyatakan properti seperti ini:

public String DiscretionCode { get; set; }
public String DiscretionDescription { get; set; }

Tapi, buat vars auxiliar, seperti lama ....

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}
Humberto Gonçalves de Almeida
sumber
1
Mengapa? Bisakah Anda memberi resonansi?
Lucenty
@Lucenty memberikan JSON seperti ini .. [{"discreationCode": "x"}], saat membuat serial.
Ammar Ameerdeen
Tapi inilah yang saya harapkan - inilah cara JSON membuat serial data. Dan menurut saya kode dengan auxiliar vars akan memberikan hasil yang sama.
Lucenty
k_BackingField telah ditambahkan untuk menunjukkan auto-property telah diserialkan. Jika Anda merefaktor auto-property menjadi property dan backing field maka masalahnya akan hilang. Saya pikir ada solusi yang lebih baik di utas ini tetapi ini berfungsi.
timB33