วิธีการลบ k__BackingField จาก json เมื่อ Deserialize


104

ฉันได้รับ k_BackingField ใน json ที่ส่งคืนของฉันหลังจากจัดไฟล์ xml เป็นไฟล์. net c #

ฉันได้เพิ่ม DataContract และแอตทริบิวต์ DataMember ลงในวัตถุ. net c # แล้ว แต่ฉันไม่ได้รับอะไรเลยใน json, client end

[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")]
}

ตัวอย่างของ json ที่ส่งคืน:

home: Object
<FirstName>k__BackingField: "Storefront"
<LastName>k__BackingField: "Doors"

คำตอบ:


45

ไม่แนะนำให้ใช้ไวยากรณ์คุณสมบัติอัตโนมัติหากคลาสสามารถใช้ในการทำให้เป็นอนุกรมได้ เหตุผลที่เป็นฟิลด์สำรองถูกสร้างขึ้นโดยคอมไพเลอร์ซึ่งอาจแตกต่างกันในแต่ละครั้งที่คอมไพล์โค้ด ซึ่งอาจทำให้เกิดปัญหาความไม่ลงรอยกันแม้ว่าจะไม่มีการเปลี่ยนแปลงใด ๆ กับคลาส (เพียงแค่คอมไพล์โค้ดใหม่)

ฉันคิดว่าการใช้แอตทริบิวต์ DataMember จะช่วยแก้ปัญหาในกรณีนี้ได้ แต่ฉันอยากจะแนะนำให้ใช้ไวยากรณ์คุณสมบัติเต็มหากจำเป็นต้องใช้คลาสในการทำให้เป็นอนุกรม


ฮ่า ๆ ใช้งานเวอร์ชันยาวและตั้งค่าฟิลด์ส่วนตัวให้กับไคลเอนต์ home: Object _fName: "Storefront" _headline: "CEO ที่ StorefrontDoors.NET" _id: "" _industry: ""
Filling The Stack is What I DO

21
การเพิ่ม datacontract นั้นไว้ที่ด้านบนสุดของชั้นเรียนและข้อมูลสมาชิกให้กับคุณสมบัติแต่ละรายการที่ฉันสนใจทำงาน
Filling The Stack is what I DO

3
@ AlumCloud.Com +1 สำหรับ [DataContract] และ [DataMember] อย่าลืมเพิ่ม: System.Runtime.Serialization
Ian Newland

109

ลบออก[Serializable]จากชั้นเรียนของคุณ


2
ตอนนี้ฉันสงสัยว่าทำไมฉันถึงคิดว่าฉันต้องการ [Serializable] ตั้งแต่แรก การทำให้อนุกรม Xml ของฉันใช้งานได้โดยไม่มีและ JSON ทำงานโดยไม่มีมัน
Rhyous

11
สิ่งนี้ใช้ไม่ได้กับบริการ WCF เมื่อส่งคืนเพย์โหลดโดยใช้บริการ RESTful จะไม่ให้ข้อมูลใด ๆ หากคุณลบ [Serializable] เพิ่ม System.Runtime.Serialization และใช้ [DataContract] สำหรับคลาส [DataMember] สำหรับคุณสมบัติ
Ian Newland

คำตอบนี้และความคิดเห็นของเอียนดูเหมือนจะครอบคลุมทั้งสองกรณี สำหรับ WCF หรือไม่กับ WCF นั่นคือคำถาม
granadaCoder

1
@Rhyous - ใน Web API คุณไม่จำเป็นต้องใช้ [Serializable] เนื่องจาก Web API ถูกตั้งค่าโดยสมมติว่าคุณกำลังจะทำให้เป็นอนุกรมและส่งคืนวัตถุของคุณ (เนื่องจากเป็นแนวคิดทั้งหมด) - ในแอปพลิเคชัน C # อื่น ๆ ที่คุณโดยทั่วไป จำเป็นต้องต่ออนุกรมเพื่อแยกความแตกต่างของวัตถุที่ต่อเนื่องกันได้
Jon Story

ขอบคุณฉันติดขัด[Serializable]การเพิ่มช่องสำรองจึงช่วยได้
ohmusama

59

WebApi serializer เริ่มต้นจะเพิ่มไวยากรณ์ "__BackingField:" ให้กับ c # auto-properties เพิ่มสิ่งนี้ลงใน WebConfig ของคุณใน App_Start เพื่อรับ json ที่ดูสะอาดตาที่คุณอาจกำลังมองหา

using Newtonsoft.Json;
...

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();

3
สิ่งนี้ช่วยแก้ปัญหาได้ ฉันคิดว่าคุณสมบัติของรถยนต์นั้นสะอาด การใช้ฟิลด์สำรองทุกที่ดูเหมือนโง่ และทำให้เกิดความยุ่งเหยิงมากมายและบางครั้งก็สับสน
Romesh D. Niriella

สิ่งนี้ได้ผลสำหรับฉัน ในกรณีของฉันฉันมีคลาสที่มีอยู่ซึ่งถูกใช้โดยบริการเว็บ WCF และ ASMX อยู่แล้วดังนั้นฉันจึงไม่สามารถเปลี่ยนมันสำหรับโปรเจ็กต์ WebAPI ใหม่ของฉันได้
samiup

4
คำถามคือเหตุใดบนโลก WebApi serializer จึงเพิ่ม "__BackingField:" ตามค่าเริ่มต้น?
Teoman shipahi

ทางออกที่ดี ในกรณีของฉันฉันต้องใช้ [Serializable] บันทึกลงใน memcache จำเป็นต้องมีการต่ออนุกรม
BìnhNguyễn Quang

2
ฉันจะทำอย่างไรหากไม่มี StackOverflow ขอบคุณ.
camainc

35

เรามีออบเจ็กต์บางอย่างที่ถูกทำเครื่องหมาย[Serializable]เพื่อให้สามารถทำให้เป็นอนุกรมได้โดยใช้วิธีการแบบเดิม แต่เราจำเป็นต้องมีอนุกรมใน JSON ทั้งหมดเพื่อใช้กับ Web API การตั้งค่าIgnoreSerializableAttributeเป็นtrueจะหยุด Newtonsoft.Json จากพฤติกรรมเหมือน serialisers ของ Microsoft และจะทำให้เป็นอนุกรมของคุณสมบัติสาธารณะแทน

TLDR: เพิ่มสิ่งนี้ใน WebApiConfig.cs:

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

ผู้ดำเนินรายการ: แทนที่จะลบคำตอบที่ดีจริงๆสำหรับคำถามที่ถูกถามหลายครั้งโปรดลบคำถามที่ซ้ำกัน นี่เป็นคำตอบที่ถูกต้องสำหรับคำถามที่ถูกต้อง


3
นี่น่าจะเป็นคำตอบที่ใช่ การลบ Serialization หรือใช้แอตทริบิวต์ datacontract และ datamember ไม่ใช่วิธีแก้ปัญหาที่ถูกต้องเสมอไป
Houssam Hamdan

พวกเราหลายคนไม่ได้รวม OP, ใช้ Webapi หรือ MVVM หรือสิ่งที่พวกคุณทำอยู่ app_start และ webapiconfig คืออะไรเมื่อฉันมีบริการ WCF สบู่ปกติกับ service.svc
คริสเตียน

10

วิธีง่ายๆที่ง่ายและเหมาะสมในการเปิดเผยข้อมูล เราจำเป็นต้องเปิดเผยข้อมูลในรูปแบบที่อ่านง่ายและสอดคล้องกัน


ก่อนอื่นให้ลบ[Serializable]

    [Serializable]

ตอนนี้เพิ่ม[DataContract]ในคลาสและ[DataMember]สำหรับคุณสมบัติดังตัวอย่างด้านล่าง

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

หวังว่านี่จะช่วยได้
ขอบคุณ


1
หากใช้ Web API ไม่จำเป็นต้องเพิ่มแอตทริบิวต์ DataContract และ DataMember เพียงแค่ส่งคืนวัตถุและจะถูกทำให้เป็นอนุกรมโดยอัตโนมัติ
Jon Story

หากใครที่เริ่มต้นการพัฒนาตั้งแต่ต้นดังนั้นจะเป็นการดีที่จะใช้ Web API ซึ่งจะให้ Object return type จะไม่ต้องใช้ type casting ใด ๆ เพื่อเปิดเผยต่อไคลเอนต์ แต่สำหรับคำถาม @ AlumCloud.com ถ้าเขาอยู่ในแอปพลิเคชันที่มีอยู่ดังนั้นวิธีแก้ปัญหาของเขาจะเป็นโดยการลบ [Serializable] ก่อนจากนั้นเพิ่ม [DataContract] ในคลาสและ [DataMember] สำหรับคุณสมบัติดังที่แนะนำด้านล่าง
Nagendra Upwanshi

1
สิ่งนี้จะเพิ่ม "เสียงรบกวน" จำนวนมากให้กับชั้นเรียนของคุณและเป็นสิ่งที่ไม่จำเป็นเป็นหลัก (ดูความคิดเห็นอื่น ๆ ทั้งหมด) อย่างไรก็ตามหากใครรู้สึกว่าจำเป็นต้องทำสิ่งนี้จริง ๆ ฉันขอแนะนำให้ใช้บางอย่างเช่น PostSharp เพื่อเพิ่มรหัสให้คุณในระหว่างการรวบรวมเพื่อไม่ให้ชั้นเรียนของคุณยุ่งเหยิงด้วยคุณสมบัติเหล่านั้นทั้งหมด
camainc

7

สองตัวเลือก:

  1. ลบออก[Serializable]จากโมเดล

  2. เพิ่ม[DataContract]และ[DataMember]ลงในโมเดลของคุณพร้อมกับ [Serializable]

  3. เพิ่มบรรทัดด้านล่างเพื่อ App_Start/WebApiConfig.cs

config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();

3

อีกวิธีหนึ่งที่อาจช่วยได้ในกรณีของ JSON.NET อาจจะเพียงพอที่จะทำเครื่องหมายคลาสด้วยแอตทริบิวต์ [Newtonsoft.Json.JsonObject]

ฉันกำลังทำงานกับคลาส cs ที่สร้างจาก xsd และกำลังเพิ่มคุณสมบัติบางอย่างโดยใช้คลาสบางส่วน หลังจากการทำให้อนุกรม json คุณสมบัติเหล่านี้ถูกทำเครื่องหมายด้วย k_BackingField การตั้งค่า JsonFormatter ที่กล่าวถึงในคำตอบอื่น ๆ ก็ช่วยได้เช่นกัน แต่ง่ายกว่านั้นคือการทำเครื่องหมายคลาสบางส่วนด้วยแอตทริบิวต์ [JsonObject]


2

ฉันใช้DataContractJsonSerializerกับคลาสจากแอสเซมบลีอื่นที่มีSerializableแอตทริบิวต์ เอาต์พุตมี "k__BackingField" การลบSerializableแอตทริบิวต์ (ในชุดประกอบอื่น ๆ ) แก้ไขสิ่งนี้ ไม่แน่ใจว่าทำไม


0

สมมติว่าคุณเห็นปัญหานี้ในโครงการ MVC ของคุณฉันพบว่ามันค่อนข้างง่ายที่จะแทนที่การใช้ @ Html.JsonData นี่คือตัวอย่างโค้ดที่ใช้งานได้สำหรับฉันในอดีต:

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

ไม่หรูหรา แต่เรียบง่ายในการหยิก


0

ฉันมีปัญหานี้เมื่อฉันมีคุณสมบัติอ้างอิงตนเองในชั้นเรียนของฉันเช่น;

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

และผลก็คือคน ๆ นั้นเป็นเพื่อนกับตัวเอง ฉันตรวจสอบให้แน่ใจว่าไม่มีวัตถุอ้างอิงตัวเองในชุดผลลัพธ์ของฉัน หวังว่านี่จะช่วยได้



0

ในกรณีของฉันข้อผิดพลาดนี้เกิดขึ้นกับ Newtonsoft เวอร์ชัน Json เซิร์ฟเวอร์ค้นหาเวอร์ชัน 6.0.0 และฉันมี 11.0 ดังนั้นฉันจึงต้องติดตั้งเวอร์ชัน 6.0.0


-2

เพื่อน ๆ อย่าประกาศสรรพคุณแบบนี้

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

แต่สร้างตัวแทนเสริมเหมือนเก่า ....

private String discretionCode;

public String DiscretionCode 
{ 
    get { return discretionCode;}
    set { discretionCode = value; }
}

1
ทำไม? คุณช่วยให้เสียงสะท้อนได้หรือไม่?
Lucenty

@Lucenty ให้ JSON แบบนี้ .. [{"discreationCode": "x"}] เมื่อทำให้เป็นอนุกรม
Ammar Ameerdeen

แต่นี่คือสิ่งที่ฉันคาดหวัง - นี่คือวิธีที่ JSON ทำให้ข้อมูลเป็นอนุกรม และฉันคิดว่าโค้ดที่มีตัวแปรช่วยจะให้ผลลัพธ์เหมือนกัน
Lucenty

เพิ่ม k_BackingField เพื่อระบุว่าคุณสมบัติอัตโนมัติได้รับการต่ออนุกรม หากคุณ refactor คุณสมบัติอัตโนมัติเป็นคุณสมบัติและฟิลด์สำรองปัญหาจะหมดไป ฉันคิดว่ามีวิธีแก้ปัญหาที่ดีกว่าในชุดข้อความนี้ แต่ใช้ได้ผล
timB33
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.