如何在 ASP.NET 中将 JSON 反序列化为简单的 Dictionary<string,string>?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1207731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:18:01  来源:igfitidea点击:

How can I deserialize JSON to a simple Dictionary<string,string> in ASP.NET?

jsonasp.net-ajaxasp.net-3.5json.net

提问by richardtallent

I have a simple key/value list in JSON being sent back to ASP.NET via POST. Example:

我有一个简单的 JSON 键/值列表,通过 POST 发送回 ASP.NET。例子:

{ "key1": "value1", "key2": "value2"}

I AM NOT TRYING TO DESERIALIZE INTO STRONGLY-TYPED .NET OBJECTS

我不是试图反序列化为强类型的 .NET 对象

I simply need a plain old Dictionary(Of String, String), or some equivalent (hash table, Dictionary(Of String, Object), old-school StringDictionary--hell, a 2-D array of strings would work for me.

我只需要一个普通的旧Dictionary(Of String, String)或一些等价物(哈希表、Dictionary(Of String, Object)、老式 StringDictionary——地狱,一个二维字符串数组对我有用。

I can use anything available in ASP.NET 3.5, as well as the popular Json.NET (which I'm already using for serialization tothe client).

我可以使用 ASP.NET 3.5 中可用的任何东西,以及流行的 Json.NET(我已经使用它来序列化客户端)。

Apparently neither of these JSON libraries have this forehead-slapping obvious capability out of the box--they are totally focused on reflection-based deserialization via strong contracts.

显然,这些 JSON 库都没有这种开箱即用的明显功能——它们完全专注于通过强契约进行基于反射的反序列化。

Any ideas?

有任何想法吗?

Limitations:

限制:

  1. I don't want to implement my own JSON parser
  2. Can't use ASP.NET 4.0 yet
  3. Would prefer to stay away from the older, deprecated ASP.NET class for JSON
  1. 我不想实现我自己的 JSON 解析器
  2. 还不能使用 ASP.NET 4.0
  3. 宁愿远离旧的、已弃用的 JSON ASP.NET 类

回答by James Newton-King

Json.NETdoes this...

Json.NET这样做...

string json = @"{""key1"":""value1"",""key2"":""value2""}";

var values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

More examples: Serializing Collections with Json.NET

更多示例:使用 Json.NET 序列化集合

回答by Crispy

I did discover .NET has a built in way to cast the JSON string into a Dictionary<String, Object>via the System.Web.Script.Serialization.JavaScriptSerializertype in the 3.5 System.Web.Extensionsassembly. Use the method DeserializeObject(String).

我确实发现 .NET 有一种内置方法可以Dictionary<String, Object>通过System.Web.Script.Serialization.JavaScriptSerializer3.5System.Web.Extensions程序集中的类型将 JSON 字符串转换为。使用方法DeserializeObject(String)

I stumbled upon this when doing an ajax post (via jquery) of content type 'application/json' to a static .net Page Method and saw that the method (which had a single parameter of type Object) magically received this Dictionary.

我在对静态 .net 页面方法执行内容类型为“application/json”的 ajax 帖子(通过 jquery)时偶然发现了这一点,并看到该方法(具有单个类型参数Object)神奇地接收了此字典。

回答by JP Richardson

For those searching the internet and stumbling upon this post, I wrote a blog post on how to use the JavaScriptSerializer class.

对于那些在互联网上搜索并偶然发现这篇文章的人,我写了一篇关于如何使用 JavaScriptSerializer 类的博客文章。

Read more... http://procbits.com/2011/04/21/quick-json-serializationdeserialization-in-c/

阅读更多... http://procbits.com/2011/04/21/quick-json-serializationdeserialization-in-c/

Here is an example:

下面是一个例子:

var json = "{\"id\":\"13\", \"value\": true}";
var jss = new JavaScriptSerializer();
var table = jss.Deserialize<dynamic>(json);
Console.WriteLine(table["id"]);
Console.WriteLine(table["value"]);

回答by PvH

Tried to not use any external JSON implementation so i deserialised like this:

试图不使用任何外部 JSON 实现,所以我反序列化如下:

string json = "{\"id\":\"13\", \"value\": true}";

var serializer = new JavaScriptSerializer(); //using System.Web.Script.Serialization;

Dictionary<string, string> values = serializer.Deserialize<Dictionary<string, string>>(json);

回答by Dasun

I had the same problem, so I wrote this my self. This solution is differentiated from other answers because it can deserialize in to multiple levels.

我有同样的问题,所以我自己写了这个。此解决方案与其他答案不同,因为它可以反序列化为多个级别。

Just send JSON string in to deserializeToDictionaryfunction it will return non strongly-typed Dictionary<string, object>object.

只需将 JSON 字符串发送到deserializeToDictionary函数,它将返回非强类型Dictionary<string, object>对象。

Old code

旧代码

private Dictionary<string, object> deserializeToDictionary(string jo)
{
    var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(jo);
    var values2 = new Dictionary<string, object>();
    foreach (KeyValuePair<string, object> d in values)
    {
        // if (d.Value.GetType().FullName.Contains("Newtonsoft.Json.Linq.JObject"))
        if (d.Value is JObject)
        {
            values2.Add(d.Key, deserializeToDictionary(d.Value.ToString()));
        }
        else
        {
            values2.Add(d.Key, d.Value);
        }
    }
    return values2;
}

Ex: This will return Dictionary<string, object>object of a Facebook JSON response.

例如:这将返回Dictionary<string, object>Facebook JSON 响应的对象。

Test

测试

private void button1_Click(object sender, EventArgs e)
{
    string responsestring = "{\"id\":\"721055828\",\"name\":\"Dasun Sameera Weerasinghe\",\"first_name\":\"Dasun\",\"middle_name\":\"Sameera\",\"last_name\":\"Weerasinghe\",\"username\":\"dasun\",\"gender\":\"male\",\"locale\":\"en_US\",  hometown: {id: \"108388329191258\", name: \"Moratuwa, Sri Lanka\",}}";
    Dictionary<string, object> values = deserializeToDictionary(responsestring);
}

Note: hometown further deserilize into a Dictionary<string, object>object.

注:故乡进一步除菌成Dictionary<string, object>物。

Update

更新

My old answer works great if there is no array on JSON string. This one further deserialize in to a List<object>if an element is an array.

如果 JSON 字符串上没有数组,我的旧答案会很好用。List<object>如果元素是数组,则进一步反序列化为 a 。

Just send a JSON string in to deserializeToDictionaryOrListfunction it will return non strongly-typed Dictionary<string, object>object or List<object>.

只需将 JSON 字符串发送到deserializeToDictionaryOrList函数,它将返回非强类型Dictionary<string, object>对象或List<object>.

private static object deserializeToDictionaryOrList(string jo,bool isArray=false)
{
    if (!isArray)
    {
        isArray = jo.Substring(0, 1) == "[";
    }
    if (!isArray)
    {
        var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(jo);
        var values2 = new Dictionary<string, object>();
        foreach (KeyValuePair<string, object> d in values)
        {
            if (d.Value is JObject)
            {
                values2.Add(d.Key, deserializeToDictionary(d.Value.ToString()));
            }
            else if (d.Value is JArray)
            {
                values2.Add(d.Key, deserializeToDictionary(d.Value.ToString(), true));
            }
            else
            {
                values2.Add(d.Key, d.Value);
            }
        }
        return values2;
    }else
    {
        var values = JsonConvert.DeserializeObject<List<object>>(jo);
        var values2 = new List<object>();
        foreach (var d in values)
        {
            if (d is JObject)
            {
                values2.Add(deserializeToDictionary(d.ToString()));
            }
            else if (d is JArray)
            {
                values2.Add(deserializeToDictionary(d.ToString(), true));
            }
            else
            {
                values2.Add(d);
            }
        }
        return values2;
    }
}

回答by dexy

If you're after a lightweight, no-added-references kind of approach, maybe this bit of code I just wrote will work (I can't 100% guarantee robustness though).

如果您采用轻量级、无添加引用的方法,也许我刚刚编写的这段代码会起作用(虽然我不能 100% 保证健壮性)。

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

public Dictionary<string, object> ParseJSON(string json)
{
    int end;
    return ParseJSON(json, 0, out end);
}
private Dictionary<string, object> ParseJSON(string json, int start, out int end)
{
    Dictionary<string, object> dict = new Dictionary<string, object>();
    bool escbegin = false;
    bool escend = false;
    bool inquotes = false;
    string key = null;
    int cend;
    StringBuilder sb = new StringBuilder();
    Dictionary<string, object> child = null;
    List<object> arraylist = null;
    Regex regex = new Regex(@"\u([0-9a-z]{4})", RegexOptions.IgnoreCase);
    int autoKey = 0;
    for (int i = start; i < json.Length; i++)
    {
        char c = json[i];
        if (c == '\') escbegin = !escbegin;
        if (!escbegin)
        {
            if (c == '"')
            {
                inquotes = !inquotes;
                if (!inquotes && arraylist != null)
                {
                    arraylist.Add(DecodeString(regex, sb.ToString()));
                    sb.Length = 0;
                }
                continue;
            }
            if (!inquotes)
            {
                switch (c)
                {
                    case '{':
                        if (i != start)
                        {
                            child = ParseJSON(json, i, out cend);
                            if (arraylist != null) arraylist.Add(child);
                            else
                            {
                                dict.Add(key, child);
                                key = null;
                            }
                            i = cend;
                        }
                        continue;
                    case '}':
                        end = i;
                        if (key != null)
                        {
                            if (arraylist != null) dict.Add(key, arraylist);
                            else dict.Add(key, DecodeString(regex, sb.ToString()));
                        }
                        return dict;
                    case '[':
                        arraylist = new List<object>();
                        continue;
                    case ']':
                        if (key == null)
                        {
                            key = "array" + autoKey.ToString();
                            autoKey++;
                        }
                        if (arraylist != null && sb.Length > 0)
                        {
                            arraylist.Add(sb.ToString());
                            sb.Length = 0;
                        }
                        dict.Add(key, arraylist);
                        arraylist = null;
                        key = null;
                        continue;
                    case ',':
                        if (arraylist == null && key != null)
                        {
                            dict.Add(key, DecodeString(regex, sb.ToString()));
                            key = null;
                            sb.Length = 0;
                        }
                        if (arraylist != null && sb.Length > 0)
                        {
                            arraylist.Add(sb.ToString());
                            sb.Length = 0;
                        }
                       continue;
                    case ':':
                        key = DecodeString(regex, sb.ToString());
                        sb.Length = 0;
                        continue;
                }
            }
        }
        sb.Append(c);
        if (escend) escbegin = false;
        if (escbegin) escend = true;
        else escend = false;
    }
    end = json.Length - 1;
    return dict; //theoretically shouldn't ever get here
}
private string DecodeString(Regex regex, string str)
{
    return Regex.Unescape(regex.Replace(str, match => char.ConvertFromUtf32(Int32.Parse(match.Groups[1].Value, System.Globalization.NumberStyles.HexNumber))));
}

[I realise that this violates the OP Limitation #1, but technically, you didn't write it, I did]

[我意识到这违反了 OP 限制 #1,但从技术上讲,不是你写的,是我写的]

回答by Falko

I just needed to parse a nesteddictionary, like

我只需要解析一个嵌套的字典,比如

{
    "x": {
        "a": 1,
        "b": 2,
        "c": 3
    }
}

where JsonConvert.DeserializeObjectdoesn't help. I found the following approach:

哪里JsonConvert.DeserializeObject没有帮助。我找到了以下方法:

var dict = JObject.Parse(json).SelectToken("x").ToObject<Dictionary<string, int>>();

The SelectTokenlets you dig down to the desired field. You can even specify a path like "x.y.z"to step further down into the JSON object.

SelectToken让你挖掘到所需的字段。您甚至可以指定一个路径,例如"x.y.z"进一步深入 JSON 对象。

回答by haldo

System.Text.Json

系统.Text.Json

This can now be done using System.Text.Jsonwhich is built-in to .net core 3.0. It's now possible to deserialize JSON withoutusing third party libraries.

现在可以使用System.Text.Json内置于.net core 3.0. 现在可以在使用第三方库的情况下反序列化 JSON 。

var json = @"{""key1"":""value1"",""key2"":""value2""}";
var values = JsonSerializer.Deserialize<Dictionary<string, string>>(json);

Also available in nu-get package System.Text.Jsonif using .Net Standard or .Net Framework.

如果使用 .Net Standard 或 .Net Framework,也可以在 nu-get 包System.Text.Json 中使用。

回答by Bryan

Mark Rendle posted this as a comment, I wanted to post it as an answer since it's the only solution that has worked so far to return the success and the error-codes json results from the Google reCaptcha response.

Mark Rendle 将此作为评论发布,我想将其发布为答案,因为它是迄今为止唯一有效的解决方案,可以从 Google reCaptcha 响应中返回成功和错误代码 json 结果。

string jsonReponseString= wClient.DownloadString(requestUrl);    
IDictionary<string, object> dict = new JavaScriptSerializer().DeserializeObject(jsonReponseString) as IDictionary<string, object>;

Thanks again, Mark!

再次感谢,马克!

回答by richardtallent

Edit:This works, but the accepted answer using Json.NET is much more straightforward. Leaving this one in case someone needs BCL-only code.

编辑:这有效,但使用 Json.NET 的公认答案要简单得多。留下这个以防有人需要 BCL-only 代码。

It's not supported by the .NET framework out of the box. A glaring oversight – not everyone needs to deserialize into objects with named properties. So I ended up rolling my own:

开箱即用的 .NET 框架不支持它。一个明显的疏忽——不是每个人都需要反序列化为具有命名属性的对象。所以我最终推出了自己的:

<Serializable()> Public Class StringStringDictionary
    Implements ISerializable
    Public dict As System.Collections.Generic.Dictionary(Of String, String)
    Public Sub New()
        dict = New System.Collections.Generic.Dictionary(Of String, String)
    End Sub
    Protected Sub New(info As SerializationInfo, _
          context As StreamingContext)
        dict = New System.Collections.Generic.Dictionary(Of String, String)
        For Each entry As SerializationEntry In info
            dict.Add(entry.Name, DirectCast(entry.Value, String))
        Next
    End Sub
    Public Sub GetObjectData(info As SerializationInfo, context As StreamingContext) Implements ISerializable.GetObjectData
        For Each key As String in dict.Keys
            info.AddValue(key, dict.Item(key))
        Next
    End Sub
End Class

Called with:

调用方式:

string MyJsonString = "{ \"key1\": \"value1\", \"key2\": \"value2\"}";
System.Runtime.Serialization.Json.DataContractJsonSerializer dcjs = new
  System.Runtime.Serialization.Json.DataContractJsonSerializer(
    typeof(StringStringDictionary));
System.IO.MemoryStream ms = new
  System.IO.MemoryStream(Encoding.UTF8.GetBytes(MyJsonString));
StringStringDictionary myfields = (StringStringDictionary)dcjs.ReadObject(ms);
Response.Write("Value of key2: " + myfields.dict["key2"]);

Sorry for the mix of C# and VB.NET…

对不起 C# 和 VB.NET 的混合......