ฉันจะทำให้ชนิดที่ไม่ระบุชื่อ C # เป็นอนุกรมเป็นสตริง JSON ได้อย่างไร


162

ฉันพยายามใช้รหัสต่อไปนี้เพื่อทำให้เป็นประเภทที่ไม่ระบุชื่อกับ JSON:

var serializer = new DataContractJsonSerializer(thing.GetType());
var ms = new MemoryStream();
serializer.WriteObject(ms, thing);
var json = Encoding.Default.GetString(ms.ToArray()); 

อย่างไรก็ตามฉันได้รับข้อยกเว้นต่อไปนี้เมื่อถูกดำเนินการ:

พิมพ์ '<> f__AnonymousType1`3 [System.Int32, System.Int32, System.Object []]' ไม่สามารถทำให้เป็นอนุกรม พิจารณาทำเครื่องหมายด้วยแอ็ตทริบิวต์ DataContractAttribute และทำเครื่องหมายสมาชิกทั้งหมดที่คุณต้องการต่อเนื่องกับแอ็ตทริบิวต์ DataMemberAttribute ดูเอกสารประกอบ Microsoft .NET Framework สำหรับประเภทอื่น ๆ ที่รองรับ

ฉันไม่สามารถใช้คุณลักษณะกับประเภทที่ไม่ระบุตัวตน (เท่าที่ฉันรู้) มีวิธีอื่นในการทำซีเรียลไลเซชั่นนี้หรือไม่

คำตอบ:


159

ลอง JavaScriptSerializer แทน DataContractJsonSerializer

JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(your_anon_object);

17
ดูเหมือนว่าแทร็กแบ็คถูกยกเลิกการใช้งานใน SP1
Biswanath

7
สำหรับบางสิ่งที่ล้าสมัยมาก ๆ ดูเหมือนว่าจะมีการใช้งานในกรอบงานใหม่ ๆ ของ Microsoft รวมถึง MVC aspnet.codeplex.com/SourceControl/changeset/view/21528#266491
Nick Berardi

1
ฉันจะรวมโครงการ ia non-asp.net นี้ (แอปพลิเคชันคอนโซล) ได้อย่างไร
Alxandr

4
@Alxandr: คุณจะต้องอ้างอิงSystem.Web.Extensions.dllและเพิ่มusing System.Web.Script.Serialization;คำสั่ง
randomguy

1
@randomgui ปัญหาถูกตั้งค่าประเภทผลลัพธ์ของโครงการเป็นโปรไฟล์ลูกค้า
Alxandr

75

อย่างที่คนอื่นพูดถึงNewtonsoft JSON.NETเป็นตัวเลือกที่ดี นี่คือตัวอย่างที่เฉพาะเจาะจงสำหรับการทำให้เป็นอนุกรม JSON อย่างง่าย:

return JsonConvert.SerializeObject(
    new
    {
       DataElement1,
       SomethingElse
    });

ฉันพบว่ามันเป็นห้องสมุดที่มีความยืดหยุ่นและใช้งานได้หลากหลาย


14

คุณสามารถลองใช้ ServiceStack JsonSerializerของฉันซึ่งเป็นserializer .NET JSON ที่เร็วที่สุดในขณะนี้ มันรองรับซีเรียลไลซ์เซชั่น DataContract, ชนิด POCO ใด ๆ , อินเทอร์เฟซ, วัตถุที่ถูกผูกปลายรวมถึงประเภทที่ไม่ระบุตัวตน ฯลฯ

ตัวอย่างพื้นฐาน

var customer = new Customer { Name="Joe Bloggs", Age=31 };
var json = customer.ToJson();
var fromJson = json.FromJson<Customer>(); 

หมายเหตุ: ใช้ Microsofts JavaScriptSerializer เฉพาะในกรณีที่ประสิทธิภาพการทำงานของคุณไม่สำคัญกับคุณเนื่องจากฉันต้องปล่อยให้มันอยู่ในเกณฑ์มาตรฐานของฉันเนื่องจากมันช้ากว่า40x-100xมากกว่า JSON serializers อื่น ๆ


7
ฉันใช้ MS JavaScriptSerializer บนสแต็ก MVC3 เพื่อทำให้วัตถุเป็นอนุกรมด้วยข้อมูลจำนวนเล็กน้อย ในกรณีเหล่านี้ค่อนข้างเร็วใช้เวลาน้อยกว่ามิลลิวินาทีในการทำสิ่งที่ฉันต้องการ แบบสอบถาม DB ตัวเองใช้เวลา 50x-100x อีกต่อไปดังนั้นมันจึงไม่ใช่คอขวดที่สำคัญในสถานการณ์ของฉัน
Brian

2
การเพิ่มประสิทธิภาพก่อนวัยอันควรคือ ... คุณรู้ไหม
Mathias Lykkegaard Lorenzen

1
ลิงค์ ". NET JSON serializer ที่เร็วที่สุด" คือ 404ing! ยิ่งกว่านั้นคำตอบนี้มีอายุมากกว่า 5 1/2 ปี คุณมีการปรับปรุงประสิทธิภาพของ serializers .NET JSON ต่างๆหรือไม่?
ErikE

11

โปรดทราบว่านี่คือปี 2008 วันนี้ฉันจะยืนยันว่าควรมีการสร้าง serializer ขึ้นและคุณสามารถใช้คุณสมบัติ swagger + เพื่อแจ้งให้ผู้บริโภคทราบเกี่ยวกับปลายทางและข้อมูลที่ส่งคืน


ฉันจะยืนยันว่าคุณไม่ควรซีเรียลไลซ์ประเภทที่ไม่ระบุชื่อ ฉันรู้ว่าสิ่งล่อใจที่นี่; คุณต้องการสร้างประเภททิ้งอย่างรวดเร็วที่จะถูกใช้ในสภาพแวดล้อมแบบหลวม ๆ หรือ Javascript ในเบราว์เซอร์ ยังฉันจะสร้างประเภทจริงและตกแต่งเป็น Serializable จากนั้นคุณสามารถพิมพ์วิธีการบนเว็บของคุณได้อย่างมาก แม้ว่าสิ่งนี้จะไม่สำคัญสำหรับ iota สำหรับ Javascript แต่จะเพิ่มเอกสารคู่มือตัวเองลงในเมธอด โปรแกรมเมอร์ที่มีประสบการณ์พอสมควรจะสามารถมองเห็นลายเซ็นของฟังก์ชั่นและพูดว่า "โอ้นี่คือประเภทฟู! ฉันรู้ว่ามันควรมีลักษณะอย่างไรใน JSON"

ต้องบอกว่าคุณอาจลองJSON.Netทำอนุกรม ฉันไม่รู้ว่ามันจะทำงานได้ไหม


3
JSON.Net ใช้งานได้ดี ฉันจะเถียงว่าคุณไม่ควร :) ฉันคิดว่ามันค่อนข้างถูกกฎหมายในหลาย ๆ กรณี
aprilchild

2
หลังจากเห็นประเภท "ทิ้ง" ที่ใช้ใน MVC ฉันสามารถเห็นการใช้ที่น่าสนใจ ฉันคิดว่ามันเป็นเครื่องมือที่มีประโยชน์มากในกล่องเครื่องมือ. Net ของคุณ
Matthew Whited

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

การยกเลิกการทำให้เป็นสไตล์ของ DataContract นั้นไม่สามารถจัดการชนิด polymorphic ได้ดี คุณต้องเขียน de-serializer ของคุณเอง การบำรุงรักษารหัสมากเกินไป
micahhoover

กรณีการใช้งานที่มีประโยชน์ประเภทที่ไม่ระบุชื่ออนุกรมเป็นประโยชน์คือการทดสอบหน่วยสำหรับ API เว็บ
howcheng

9

วิธีที่เร็วที่สุดที่ฉันพบคือ:

var obj = new {Id = thing.Id, Name = thing.Name, Age = 30};
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(obj);

Namespace: System.Web.Script.Serialization.JavaScriptSerializer


2
และสำหรับการดีซีเรียลไลเซชัน:. . ไดนามิก myObject = JsonConvert.DeserializeObject <dynamic> (เอาต์พุต); . . ข้อมูลอ้างอิง: Newtonsoft.json.dll
i31nGo


1

สมมติว่าคุณใช้สิ่งนี้กับบริการบนเว็บคุณสามารถใช้คุณลักษณะต่อไปนี้กับคลาสได้:

[System.Web.Script.Services.ScriptService]

จากนั้นแอ็ตทริบิวต์ต่อไปนี้สำหรับแต่ละวิธีที่ควรคืนค่า Json:

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

และตั้งค่าชนิดส่งคืนสำหรับวิธีการให้เป็น "วัตถุ"


สำหรับบริการเว็บ ASP มาตรฐาน [ScriptMethod (ResponseFormat = ResponseFormat.Json)] ไม่จำเป็นต้องใช้ในวิธีการ [WebMethod] จะทำ นอกจากนี้คุณไม่ควรตั้งค่าชนิดส่งคืนเป็นวัตถุสามารถและควรพิมพ์อย่างยิ่งด้วยประเภทที่ไม่ซับซ้อน (เช่นสามารถเป็นอนุกรม)
แถว 1

-1
public static class JsonSerializer
{
    public static string Serialize<T>(this T data)
    {
        try
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
            var stream = new MemoryStream();
            serializer.WriteObject(stream, data);
            string jsonData = Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);
            stream.Close();
            return jsonData;
        }
        catch
        {
            return "";
        }
    }
    public static T Deserialize<T>(this string jsonData)
    {
        try
        {
            DataContractJsonSerializer slzr = new DataContractJsonSerializer(typeof(T));
            var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonData));
            T data = (T)slzr.ReadObject(stream);
            stream.Close();
            return data;
        }
        catch
        {
            return default(T);
        }
    }
}

สิ่งนี้ไม่ได้เรียงลำดับประเภทที่ไม่ระบุชื่อตามคำถาม
Mark Sowul
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.