ฉันจะแปลงพจนานุกรมเป็นสตริง JSON ใน C # ได้อย่างไร


131

ฉันต้องการแปลงDictionary<int,List<int>>เป็นสตริง JSON ไม่มีใครรู้วิธีบรรลุสิ่งนี้ใน C #?


3
ใช้แพ็คเกจ nuget newtonSoft.json JsonConvert.SerializeObject (yourObject)
RayLoveless

คำตอบ:


119

โครงสร้างข้อมูลอนุกรมที่มีเฉพาะค่าตัวเลขหรือค่าบูลีนนั้นค่อนข้างตรงไปตรงมา หากคุณไม่ต้องทำให้เป็นอนุกรมมากนักคุณสามารถเขียนวิธีการสำหรับประเภทเฉพาะของคุณได้

สำหรับDictionary<int, List<int>>ในขณะที่คุณได้ระบุคุณสามารถใช้ Linq:

string MyDictionaryToJson(Dictionary<int, List<int>> dict)
{
    var entries = dict.Select(d =>
        string.Format("\"{0}\": [{1}]", d.Key, string.Join(",", d.Value)));
    return "{" + string.Join(",", entries) + "}";
}

แต่ถ้าคุณจัดลำดับคลาสที่แตกต่างกันหลายคลาสหรือโครงสร้างข้อมูลที่ซับซ้อนมากขึ้นหรือโดยเฉพาะอย่างยิ่งหากข้อมูลของคุณมีค่าสตริงคุณควรใช้ไลบรารี JSON ที่มีชื่อเสียงซึ่งรู้วิธีจัดการกับสิ่งต่างๆเช่นอักขระ Escape และตัวแบ่งบรรทัด Json.NETเป็นตัวเลือกยอดนิยม


67
วิธีนี้ไร้เดียงสาที่สุด ใช้ไลบรารีอนุกรม json จริง
jacobsimeon

131
@ จาค็อบ - ไร้เดียงสา? อุ๊ยตาย โดยส่วนตัวแล้วฉันไม่สามารถปรับการรวมชุดประกอบอื่นได้ในเมื่อสิ่งที่ฉันต้องทำสามารถทำได้ด้วยวิธีการสั้น ๆ เพียงวิธีเดียว
gilly3

16
อีกหนึ่ง + ใน gilly3 ความคิดเห็น บางครั้งคุณกำลังเขียนโค้ดบน Windows Phone คุณกำลังเพิ่ม zlip, twitter, google, สิ่งที่ประมวลผลเสียง, การประมวลผลภาพ คุณควรใช้วิธีง่ายๆเช่นนี้ดีกว่าและ HttpRequests พื้นฐานสำหรับการโต้ตอบกับโซเชียลมีเดียหากการใช้งานของคุณเรียบง่าย เมื่อเพิ่มแอสเซมบลีคุณต้องจัดการกับบั๊กเสมอและด้วยความเป็นไปไม่ได้ที่จะได้รับเวอร์ชันไลต์ อย่างไรก็ตามภายใน json libs มีวิธีการที่ไร้เดียงสาเช่นนี้และไม่มีเวทมนตร์
Léon Pelletier

14
ควรมีหน้าในทุกโปรเจ็กต์ที่เปิดอยู่เพื่อบอกคุณว่า: "เฮ้โดยส่วนใหญ่คุณจะต้องการดำเนินการ 10 บรรทัดเท่านั้นนี่คือรหัส"
Léon Pelletier

32
dict.add ("RandomKey \" "," RandomValue \ ""); BOOOOOOOOOOOOOOOOM ไร้เดียงสาที่ดีที่สุด ใช้ไลบรารีอนุกรม json จริง
Sleeper Smith

112

คำตอบนี้กล่าวถึง Json.NET แต่จะไม่บอกคุณว่าคุณสามารถใช้ Json.NET เพื่อจัดลำดับพจนานุกรมได้อย่างไร:

return JsonConvert.SerializeObject( myDictionary );

ตรงข้ามกับ JavaScriptSerializer myDictionaryไม่จำเป็นต้องเป็นพจนานุกรมประเภท<string, string>เพื่อให้ JsonConvert ทำงานได้


71

Json.NETอาจจัดลำดับพจนานุกรม C # ให้เพียงพอในตอนนี้ แต่เมื่อ OP โพสต์คำถามนี้ครั้งแรกนักพัฒนา MVC หลายคนอาจใช้JavaScriptSerializerคลาสเนื่องจากเป็นตัวเลือกเริ่มต้นนอกกรอบ

หากคุณกำลังทำงานในโครงการเดิม (MVC 1 หรือ MVC 2) และคุณไม่สามารถใช้ Json.NET ได้ฉันขอแนะนำให้คุณใช้ a List<KeyValuePair<K,V>>แทนDictionary<K,V>> . คลาส JavaScriptSerializer แบบเดิมจะทำให้เป็นอนุกรมประเภทนี้ได้ดี แต่จะมีปัญหากับพจนานุกรม

เอกสารประกอบ: Serializing Collections ด้วย Json.NET


3
คำตอบที่สมบูรณ์แบบสำหรับผู้ใช้ asp.net mvc3 และ mvc4
Gomes

JsonConvert.SerializeObject ไม่สามารถจัดการกับการจัดลำดับพจนานุกรม c # ให้เป็นคอลเลกชันที่แจกแจงได้เมื่ออ่านกลับไปที่ Javascript แต่มันทำให้วัตถุที่แต่ละคู่ในคอลเลกชัน C # ตอนนี้เป็นคุณสมบัติ / ค่าธรรมดาในวัตถุซึ่งไม่สามารถแจกแจงได้ง่ายเหมือนคอลเลกชัน ดังนั้นหากฉันไม่มีเวอร์ชันที่ไม่ดีจาก nuget Json.NET ก็ยังไม่เพียงพอในเรื่องนี้
StingyJack

โอ้ใช่. ฉันทำสิ่งที่คล้ายกันอยู่แล้ว แต่พยายามหาวิธีอื่นและสะดุดกับสิ่งนี้ ฉันรู้สึกว่าการบอกให้คนอื่นรู้เพื่อหลีกเลี่ยงช่องกระต่าย Json.NET สำหรับรายการนี้อาจเป็นประโยชน์
StingyJack

20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Json;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<int, List<int>> foo = new Dictionary<int, List<int>>();

            foo.Add(1, new List<int>( new int[] { 1, 2, 3, 4 }));
            foo.Add(2, new List<int>(new int[] { 2, 3, 4, 1 }));
            foo.Add(3, new List<int>(new int[] { 3, 4, 1, 2 }));
            foo.Add(4, new List<int>(new int[] { 4, 1, 2, 3 }));

            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary<int, List<int>>));

            using (MemoryStream ms = new MemoryStream())
            {
                serializer.WriteObject(ms, foo);
                Console.WriteLine(Encoding.Default.GetString(ms.ToArray()));
            }
        }
    }
}

สิ่งนี้จะเขียนไปที่คอนโซล:

[{\"Key\":1,\"Value\":[1,2,3,4]},{\"Key\":2,\"Value\":[2,3,4,1]},{\"Key\":3,\"Value\":[3,4,1,2]},{\"Key\":4,\"Value\":[4,1,2,3]}]

19

คำตอบง่ายๆเพียงบรรทัดเดียว

( using System.Web.Script.Serialization)

รหัสนี้จะแปลงใด ๆDictionary<Key,Value>ไปDictionary<string,string>แล้วอันดับเป็นสตริง JSON:

var json = new JavaScriptSerializer().Serialize(yourDictionary.ToDictionary(item => item.Key.ToString(), item => item.Value.ToString()));

ควรทราบว่าสิ่งที่ต้องการDictionary<int, MyClass>สามารถทำให้เป็นอนุกรมได้ด้วยวิธีนี้ในขณะที่รักษาประเภท / วัตถุที่ซับซ้อน


คำอธิบาย (รายละเอียด)

var yourDictionary = new Dictionary<Key,Value>(); //This is just to represent your current Dictionary.

คุณสามารถแทนที่ตัวแปรyourDictionaryด้วยตัวแปรจริงของคุณ

var convertedDictionary = yourDictionary.ToDictionary(item => item.Key.ToString(), item => item.Value.ToString()); //This converts your dictionary to have the Key and Value of type string.

เราทำเช่นนี้เนื่องจากทั้งคีย์และค่าต้องเป็นสตริงประเภทตามข้อกำหนดสำหรับการทำให้เป็นอนุกรมของไฟล์Dictionary.

var json = new JavaScriptSerializer().Serialize(convertedDictionary); //You can then serialize the Dictionary, as both the Key and Value is of type string, which is required for serialization.

ฉันไม่มี JavaScriptSerializer ใน C # ของฉัน
จอนนี่

1
@ จอนนี่คุณไม่มีข้อมูลอ้างอิง System.Web.Extensions msdn.microsoft.com/en-us/library/…
aminhotob

ฉันอ่านแล้วว่าไม่ได้System.Web.Extensionsอยู่ในเวอร์ชัน Client Framework แต่ต้องการเวอร์ชันเต็มด้วย
vapcguy

อาจเป็นวิธีแก้ปัญหาสำหรับแอ็พพลิเคชันที่ จำกัด แต่การบังคับให้ค่าทั้งหมดพิมพ์สตริงจะไม่ให้ JSON ที่ถูกต้องหากคุณสมบัติอ็อบเจ็กต์ใด ๆ ไม่ใช่สตริงประเภท
Suncat2000

1
คำตอบที่ดีที่สุดสำหรับหัวข้อนี้
T.Todua

12

ขออภัยหากไวยากรณ์เป็นบิตที่น้อยที่สุด แต่รหัสที่ฉันได้รับจากเดิมอยู่ใน VB :)

using System.Web.Script.Serialization;

...

Dictionary<int,List<int>> MyObj = new Dictionary<int,List<int>>();

//Populate it here...

string myJsonString = (new JavaScriptSerializer()).Serialize(MyObj);

2
มันพ่น ArgumentException: Type 'System.Collections.Generic.Dictionary'2 ไม่ได้รับการสนับสนุนสำหรับ serialization / deserialization ของพจนานุกรมคีย์ต้องเป็นสตริงหรือวัตถุ
Pavel Chuchuva


7

ใน Asp.net Core ใช้:

using Newtonsoft.Json

var obj = new { MyValue = 1 };
var json = JsonConvert.SerializeObject(obj);
var obj2 = JsonConvert.DeserializeObject(json);

ฉันอ้างถึงSystem.Coreแล้วพยายามอ้างอิงusing Newtonsoft.Jsonและไม่มีความสุข ฉันคิดว่าNewtonsoftเป็นไลบรารีของบุคคลที่สาม
vapcguy

2
@vapcguy ใช่ Newtonsoft เป็นบุคคลที่สาม แต่ MS ใช้กันอย่างแพร่หลายและนำมาใช้ในผลิตภัณฑ์ของตน nuget.org/packages/Newtonsoft.Json
Skorunka František

7

คุณสามารถใช้System.Web.Script.Serialization.JavaScriptSerializer:

Dictionary<string, object> dictss = new Dictionary<string, object>(){
   {"User", "Mr.Joshua"},
   {"Pass", "4324"},
};

string jsonString = (new JavaScriptSerializer()).Serialize((object)dictss);

2

นี่คือวิธีดำเนินการโดยใช้ไลบรารี. Net มาตรฐานจาก Microsoft ...

using System.IO;
using System.Runtime.Serialization.Json;

private static string DataToJson<T>(T data)
{
    MemoryStream stream = new MemoryStream();

    DataContractJsonSerializer serialiser = new DataContractJsonSerializer(
        data.GetType(),
        new DataContractJsonSerializerSettings()
        {
            UseSimpleDictionaryFormat = true
        });

    serialiser.WriteObject(stream, data);

    return Encoding.UTF8.GetString(stream.ToArray());
}

เราสามารถรวมสิ่งนี้เข้าด้วยกันDictionary<string, dynamic>และมี JSON primitive ทุกประเภทเช่น intergers, float, booleans, strings, แม้แต่ nulls และภายในออบเจ็กต์เดียว +1
Christos Lytras

1

คุณสามารถใช้JavaScriptSerializer


พจนานุกรมเป็นอนุกรมได้หรือไม่
Numenor

ฉันคิดว่ามันจะได้ผล - string json = serializer.Serialize ((object) dict);
Twelve47

1
@Numenor ใช่พวกเขามี stringแต่เฉพาะในกรณีที่และความคุ้มค่าที่สำคัญเป็นประเภท ฉันได้โพสต์คำตอบไว้ที่นี่ซึ่งรวมถึงสิ่งนั้นหากคุณต้องการดู
HowlinWulf

@HowlinWulf เพื่อให้ถูกต้องมากขึ้นค่าไม่จำเป็นต้องเป็นสตริง แต่สำหรับคีย์นั้นไม่สามารถเป็น int ได้อย่างแน่นอน สตริงทำงานได้ดีที่สุดเป็นคีย์
Gyum Fox

1
@ Twelve47 ควรมีตัวอย่างการใช้งานในกรณีที่ลิงก์ถูกย้าย ไม่เช่นนั้นคำตอบนี้อาจไร้ประโยชน์ในวันหนึ่ง
vapcguy

1

ดูเหมือนห้องสมุดต่างๆมากมายและสิ่งที่ดูเหมือนจะไม่เกิดขึ้นในช่วงหลายปีที่ผ่านมา อย่างไรก็ตามเมื่อเดือนเมษายน 2016 วิธีนี้ใช้ได้ผลดีสำหรับฉัน สตริงถูกแทนที่ด้วย ints ได้อย่างง่ายดายints

TL / DR; คัดลอกสิ่งนี้หากนั่นคือสิ่งที่คุณมาที่นี่เพื่อ:

    //outputfilename will be something like: "C:/MyFolder/MyFile.txt"
    void WriteDictionaryAsJson(Dictionary<string, List<string>> myDict, string outputfilename)
    {
        DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(Dictionary<string, List<string>>));
        MemoryStream ms = new MemoryStream();
        js.WriteObject(ms, myDict); //Does the serialization.

        StreamWriter streamwriter = new StreamWriter(outputfilename);
        streamwriter.AutoFlush = true; // Without this, I've run into issues with the stream being "full"...this solves that problem.

        ms.Position = 0; //ms contains our data in json format, so let's start from the beginning
        StreamReader sr = new StreamReader(ms); //Read all of our memory
        streamwriter.WriteLine(sr.ReadToEnd()); // and write it out.

        ms.Close(); //Shutdown everything since we're done.
        streamwriter.Close();
        sr.Close();
    }

จุดนำเข้าสองจุด ก่อนอื่นอย่าลืมเพิ่ม System.Runtime.Serliazation เป็นข้อมูลอ้างอิงในโครงการของคุณภายใน Solution Explorer ของ Visual Studio อย่างที่สองเพิ่มบรรทัดนี้

using System.Runtime.Serialization.Json;

ที่ด้านบนของไฟล์พร้อมกับการใช้งานที่เหลือของคุณเพื่อให้DataContractJsonSerializerสามารถพบคลาสได้ โพสต์บล็อกนี้มีข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำให้เป็นอนุกรมนี้

รูปแบบข้อมูล (อินพุต / เอาต์พุต)

ข้อมูลของฉันคือพจนานุกรมที่มี 3 สตริงแต่ละสตริงจะชี้ไปที่รายการของสตริง รายการสตริงมีความยาว 3, 4 และ 1 ข้อมูลมีลักษณะดังนี้:

StringKeyofDictionary1 => ["abc","def","ghi"]
StringKeyofDictionary2 => ["String01","String02","String03","String04"]
Stringkey3 => ["someString"]

ผลลัพธ์ที่เขียนไปยังไฟล์จะอยู่ในบรรทัดเดียวนี่คือผลลัพธ์ที่จัดรูปแบบ:

 [{
     "Key": "StringKeyofDictionary1",
     "Value": ["abc",
     "def",
     "ghi"]
 },
 {
     "Key": "StringKeyofDictionary2",
     "Value": ["String01",
     "String02",
     "String03",
     "String04",
 ]
 },
 {
     "Key": "Stringkey3",
     "Value": ["SomeString"]
 }]

0

สิ่งนี้คล้ายกับที่ Meritt ได้โพสต์ไว้ก่อนหน้านี้ เพียงแค่โพสต์รหัสที่สมบูรณ์

    string sJSON;
    Dictionary<string, string> aa1 = new Dictionary<string, string>();
    aa1.Add("one", "1"); aa1.Add("two", "2"); aa1.Add("three", "3");
    Console.Write("JSON form of Person object: ");

    sJSON = WriteFromObject(aa1);
    Console.WriteLine(sJSON);

    Dictionary<string, string> aaret = new Dictionary<string, string>();
    aaret = ReadToObject<Dictionary<string, string>>(sJSON);

    public static string WriteFromObject(object obj)
    {            
        byte[] json;
            //Create a stream to serialize the object to.  
        using (MemoryStream ms = new MemoryStream())
        {                
            // Serializer the object to the stream.  
            DataContractJsonSerializer ser = new DataContractJsonSerializer(obj.GetType());
            ser.WriteObject(ms, obj);
            json = ms.ToArray();
            ms.Close();
        }
        return Encoding.UTF8.GetString(json, 0, json.Length);

    }

    // Deserialize a JSON stream to object.  
    public static T ReadToObject<T>(string json) where T : class, new()
    {
        T deserializedObject = new T();
        using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        {

            DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedObject.GetType());
            deserializedObject = ser.ReadObject(ms) as T;
            ms.Close();
        }
        return deserializedObject;
    }

0

หากบริบทของคุณอนุญาต (ข้อ จำกัด ทางเทคนิค ฯลฯ ) ให้ใช้JsonConvert.SerializeObjectวิธีการจากNewtonsoft.Json : มันจะทำให้ชีวิตของคุณง่ายขึ้น

Dictionary<string, string> localizedWelcomeLabels = new Dictionary<string, string>();
localizedWelcomeLabels.Add("en", "Welcome");
localizedWelcomeLabels.Add("fr", "Bienvenue");
localizedWelcomeLabels.Add("de", "Willkommen");
Console.WriteLine(JsonConvert.SerializeObject(localizedWelcomeLabels));

// Outputs : {"en":"Welcome","fr":"Bienvenue","de":"Willkommen"}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.