문제

JSON의 간단한 키/값 목록이 게시물을 통해 ASP.NET으로 다시 전송됩니다. 예시:

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

나는 강하게 유형의 .NET 객체로 사라지는 것을 시도하지 않습니다.

나는 단순히 평범한 늙음이 필요합니다 사전 (문자열, 문자열), 또는 일부 동등한 (해시 테이블, 사전 (문자열, 개체), 구식 문자열 사학-hell, 2D 배열이 나에게 효과적입니다.

ASP.NET 3.5에서 사용 가능한 모든 것을 사용할 수 있으며 인기있는 JSON.NET (이미 직렬화에 이미 사용하고있는 것입니다. 에게 클라이언트).

분명히이 JSON 라이브러리 중 어느 것도 상자 에서이 이마를 끄는 명백한 기능을 가지고 있지 않습니다. 그들은 강력한 계약을 통한 반사 기반 사제에 전적으로 초점을 맞추고 있습니다.

어떤 아이디어?

제한 사항 :

  1. 나는 내 자신의 JSON 파서를 구현하고 싶지 않습니다
  2. 아직 ASP.NET 4.0을 사용할 수 없습니다
  3. JSON의 오래된 감가 상각 된 ASP.NET 클래스에서 멀리 떨어져있는 것을 선호합니다.
도움이 되었습니까?

해결책

json.net은 이것을합니다 ...

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

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

더 많은 예 : json.net과의 수집을 직렬화합니다

다른 팁

.NET가 JSON 문자열을 Dictionary<String, Object> TH를 통해 System.Web.Script.Serialization.JavaScriptSerializer 3.5를 입력하십시오 System.Web.Extensions 집회. 방법을 사용하십시오 DeserializeObject(String).

컨텐츠 유형 'Application/JSON'의 ajax 게시물 (jQuery를 통해)을 정적 .NET 페이지 메소드로 수행 할 때이 문제를 발견했으며 방법 (단일 유형 매개 변수가있는 메소드가 있음을 알았습니다. Object) 마술처럼이 사전을 받았다.

인터넷을 검색 하고이 게시물에 걸려 넘어지는 사람들을 위해 JavascriptSerializer 클래스 사용 방법에 대한 블로그 게시물을 썼습니다.

더 읽기 ...http://procbits.com/2011/04/21/quick-json-serializationdeserialization-in-c/

예는 다음과 같습니다.

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

외부 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);

나는 같은 문제가 있었기 때문에 이것을 내 자신을 썼습니다. 이 솔루션은 여러 수준으로 사로화 할 수 있기 때문에 다른 답변과 차별화됩니다.

JSON 문자열을 보내기 만하면됩니다 deserializetodictionary 함수는 강하게 반환합니다 Dictionary<string, object> 물체.

오래된 코드

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;
}

예 : 이것은 돌아올 것입니다 Dictionary<string, object> Facebook JSON 응답의 대상.

테스트

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);
}

참고 : 고향은 더 멀리 떨어져 a Dictionary<string, object>물체.

업데이트

JSON 문자열에 배열이 없으면 오래된 대답이 잘 작동합니다. 이것은 더 이상의 a에 사로화됩니다 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;
    }
}

가볍고 무례한 참조가 다가 오면 내가 방금 쓴이 코드가 효과가있을 것입니다 (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))));
}

나는 이것이 OP 제한 #1을 위반한다는 것을 알고 있지만 기술적으로는 글을 쓰지 않았다.

방금 구문 분석해야했습니다 중첩 사전, 좋아요

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

어디 JsonConvert.DeserializeObject 도움이되지 않습니다. 다음 접근법을 찾았습니다.

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

그만큼 SelectToken 원하는 필드로 파헤칠 수 있습니다. 당신은 같은 경로를 지정할 수도 있습니다 "x.y.z" JSON 객체로 더 내려 가기 위해.

편집하다: 이것은 작동하지만 json.net을 사용하여 허용 된 답변은 훨씬 간단합니다. 누군가 BCL 전용 코드가 필요한 경우에 이것을 남겨 두십시오.

.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

호출 :

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"]);

C#과 vb.net의 혼합에 대해 죄송합니다…

본인은 JSNAKE04와 DASUN이 제출 한 코드를 여기에 추가했습니다. 객체 목록을 작성하기 위해 코드를 추가했습니다 JArray 인스턴스. 양방향 재귀가 있지만 고정 된 유한 트리 모델에서 작동하기 때문에 데이터가 방대하지 않으면 스택 오버플로의 위험이 없습니다.

/// <summary>
/// Deserialize the given JSON string data (<paramref name="data"/>) into a
///   dictionary.
/// </summary>
/// <param name="data">JSON string.</param>
/// <returns>Deserialized dictionary.</returns>
private IDictionary<string, object> DeserializeData(string data)
{
    var values = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);

    return DeserializeData(values);
}

/// <summary>
/// Deserialize the given JSON object (<paramref name="data"/>) into a dictionary.
/// </summary>
/// <param name="data">JSON object.</param>
/// <returns>Deserialized dictionary.</returns>
private IDictionary<string, object> DeserializeData(JObject data)
{
    var dict = data.ToObject<Dictionary<String, Object>>();

    return DeserializeData(dict);
}

/// <summary>
/// Deserialize any elements of the given data dictionary (<paramref name="data"/>) 
///   that are JSON object or JSON arrays into dictionaries or lists respectively.
/// </summary>
/// <param name="data">Data dictionary.</param>
/// <returns>Deserialized dictionary.</returns>
private IDictionary<string, object> DeserializeData(IDictionary<string, object> data)
{
    foreach (var key in data.Keys.ToArray()) 
    {
        var value = data[key];

        if (value is JObject)
            data[key] = DeserializeData(value as JObject);

        if (value is JArray)
            data[key] = DeserializeData(value as JArray);
    }

    return data;
}

/// <summary>
/// Deserialize the given JSON array (<paramref name="data"/>) into a list.
/// </summary>
/// <param name="data">Data dictionary.</param>
/// <returns>Deserialized list.</returns>
private IList<Object> DeserializeData(JArray data)
{
    var list = data.ToObject<List<Object>>();

    for (int i = 0; i < list.Count; i++)
    {
        var value = list[i];

        if (value is JObject)
            list[i] = DeserializeData(value as JObject);

        if (value is JArray)
            list[i] = DeserializeData(value as JArray);
    }

    return list;
}

JSON의 NULL 값에 대한 검사를 다른 답변에 추가했습니다.

나는 같은 문제가 있었기 때문에 이것을 내 자신을 썼습니다. 이 솔루션은 여러 수준으로 사로화 할 수 있기 때문에 다른 답변과 차별화됩니다.

JSON 문자열을 보내기 만하면됩니다 deserializetodictionary 함수는 강하게 반환합니다 Dictionary<string, object> 물체.

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 != null && d.Value.GetType().FullName.Contains("Newtonsoft.Json.Linq.JObject"))
        {
            values2.Add(d.Key, deserializeToDictionary(d.Value.ToString()));
        }
        else
        {
            values2.Add(d.Key, d.Value);
        }
    }
    return values2;
}

예 : 이것은 돌아올 것입니다 Dictionary<string, object> Facebook JSON 응답의 대상.

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);
}

참고 : 고향은 더 이상의 a Dictionary<string, object> 물체.

Mark Rendle이 이것을 게시했습니다 의견으로, 나는 지금까지 성공을 거두기 위해 노력한 유일한 솔루션이기 때문에 답으로 게시하고 싶었고 Google Recaptcha 응답의 오류 코드 JSON이 결과를 거두었습니다.

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

다시 한 번 감사드립니다, 마크!

의견을 기반으로합니다 ~ 위에 노력하다 JsonConvert.DeserializeObject<Dictionary<string,dynamic>>(json)

var json = @"{""key1"":1,""key2"":""value2"", ""object1"":{""property1"":""value1"",""property2"":[2,3,4,5,6,7]}}";
var parsedObject = JsonConvert.DeserializeObject<Dictionary<string,dynamic>>(json);

복잡한 개체와 목록에서도 작동하는 것 같습니다.

이 모든 대답은 여기서 더 큰 물체에서 그 작은 끈을 얻을 수 있다고 가정합니다 ... 매핑 내부의 어딘가에 그러한 사전이있는 큰 물체를 단순히 버리고 자하는 사람들은 System.Runtime.Serialization.Json DataContract 시스템, 다음은 해결책입니다.

gis.stackexchange.com에 대한 답변 가졌다 이 흥미로운 링크. Archive.org로 복구해야했지만 완벽한 솔루션을 제공합니다. IDataContractSurrogate 자신의 유형을 정확히 구현하는 클래스. 쉽게 확장 할 수있었습니다.

그래도 나는 그것에 많은 변화를 일으켰다. 원래 소스를 더 이상 사용할 수 없으므로 여기에 전체 클래스를 게시하겠습니다.

using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;

namespace JsonTools
{
    /// <summary>
    /// Allows using Dictionary&lt;String,String&gt; and Dictionary&lt;String,Boolean&gt; types, and any others you'd like to add.
    /// Source: https://web.archive.org/web/20100317222656/my6solutions.com/post/2009/06/30/DataContractSerializer-DataContractJsonSerializer-JavaScriptSerializer-XmlSerializer-for-serialization.aspx
    /// </summary>
    public class JsonSurrogate : IDataContractSurrogate
    {
        /// <summary>
        /// Deserialize an object with added support for the types defined in this class.
        /// </summary>
        /// <typeparam name="T">Contract class</typeparam>
        /// <param name="json">JSON String</param>
        /// <param name="encoding">Text encoding</param>
        /// <returns>The deserialized object of type T</returns>
        public static T Deserialize<T>(String json, Encoding encoding)
        {
            if (encoding == null)
                encoding = new UTF8Encoding(false);
            DataContractJsonSerializer deserializer = new DataContractJsonSerializer(
                typeof(T), new Type[0], int.MaxValue, true, new JsonSurrogate(), false);
            using (MemoryStream stream = new MemoryStream(encoding.GetBytes(json)))
            {
                T result = (T)deserializer.ReadObject(stream);
                return result;
            }
        }

        // make sure all values in this are classes implementing JsonSurrogateObject.
        private static Dictionary<Type, Type> KnownTypes = 
            new Dictionary<Type, Type>()
            {
                {typeof(Dictionary<String, String>), typeof(SSDictionary)},
                {typeof(Dictionary<String, Boolean>), typeof(SBDictionary)}
            };

        #region Implemented surrogate dictionary classes

        [Serializable]
        public class SSDictionary : SurrogateDictionary<String>
        {
            public SSDictionary() : base() {}
            protected SSDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {}
        }
        [Serializable]
        public class SBDictionary : SurrogateDictionary<Boolean>
        {
            public SBDictionary() : base() {}
            protected SBDictionary (SerializationInfo info, StreamingContext context) : base(info, context) {}
        }

        #endregion

        /// <summary>Small interface to easily extract the final value from the object.</summary>
        public interface JsonSurrogateObject
        {
            Object DeserializedObject { get; }
        }

        /// <summary>
        /// Class for deserializing any simple dictionary types with a string as key.
        /// </summary>
        /// <typeparam name="T">Any simple type that will be deserialized correctly.</typeparam>
            [Serializable]
        public abstract class SurrogateDictionary<T> : ISerializable, JsonSurrogateObject
        {
            public Object DeserializedObject { get { return dict; } }
            private Dictionary<String, T> dict;

            public SurrogateDictionary()
            {
                dict = new Dictionary<String, T>();
            }

            // deserialize
            protected SurrogateDictionary(SerializationInfo info, StreamingContext context)
            {
                dict = new Dictionary<String, T>();
                foreach (SerializationEntry entry in info)
                {
                    // This cast will only work for base types, of course.
                    dict.Add(entry.Name, (T)entry.Value);
                }
            }
            // serialize
            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {
                foreach (String key in dict.Keys)
                {
                    info.AddValue(key, dict[key]);
                }
            }

        }

        /// <summary>
            /// Uses the KnownTypes dictionary to get the surrogate classes.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public Type GetDataContractType(Type type)
        {
            Type returnType;
            if (KnownTypes.TryGetValue(type, out returnType))
            {
                return returnType;
            }
            return type;
        }

        public object GetObjectToSerialize(object obj, Type targetType)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///     Gets the object out of the surrogate datacontract object. This function is the reason all surrogate objects need to implement the JsonSurrogateObject class.
        /// </summary>
        /// <param name="obj">Result of the deserialization</param>
        /// <param name="targetType">Expected target type of the deserialization</param>
        /// <returns></returns>
        public object GetDeserializedObject(object obj, Type targetType)
        {
            if (obj is JsonSurrogateObject)
            {
                return ((JsonSurrogateObject)obj).DeserializedObject;
            }
            return obj;
        }

        public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
        {
            return null;
        }

        #region not implemented

        public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
        {
            throw new NotImplementedException();
        }

        public object GetCustomDataToExport(Type clrType, Type dataContractType)
        {
            throw new NotImplementedException();
        }

        public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
        {
            throw new NotImplementedException();
        }

        public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

클래스에 새로운 지원 유형을 추가하려면 클래스를 추가하고 올바른 생성자와 기능을 제공하면됩니다. SurrogateDictionary 예를 들어) 상속받는 지 확인하십시오 JsonSurrogateObject, 유형 매핑을 추가하십시오 KnownTypes 사전. 포함 된 대리도는 어떤 기초가 될 수 있습니다 Dictionary<String,T> T가 올바르게 사로화하는 유형 인 유형.

그것을 부르는 것은 정말 간단합니다.

MyObjtype newObj = JsonSurrogate.Deserialize<MyObjtype>(jsonStr, encoding);

어떤 이유로 든이 일은 공백을 포함하는 주요 문자열을 사용하는 데 어려움이 있습니다. 그들은 단순히 최종 목록에 존재하지 않았습니다. 단순히 JSON 사양에 반하는 것일 수도 있고 내가 부르는 API는 제대로 구현되지 않았습니다. 나는 몰라. 어쨌든, 나는 REAB JSON 데이터의 밑줄로 Regex를 reglact으로 만들고 사막화 후 사전을 고정함으로써 이것을 해결했습니다.

방금 이것을 구현했습니다 Restsharp. 이 게시물 나에게 도움이되었다.

링크의 코드 외에 여기 내 코드가 있습니다. 나는 이제 a를 얻는다 Dictionary 내가 다음과 같이 할 때 결과 :

var jsonClient = new RestClient(url.Host);
jsonClient.AddHandler("application/json", new DynamicJsonDeserializer());
var jsonRequest = new RestRequest(url.Query, Method.GET);
Dictionary<string, dynamic> response = jsonClient.Execute<JObject>(jsonRequest).Data.ToObject<Dictionary<string, dynamic>>();

당신이 기대하는 JSON의 종류를 염두에두고 있습니다. 제 경우에는 여러 속성이있는 단일 객체를 검색하고있었습니다. 첨부 된 링크에서 저자는 목록을 검색하고있었습니다.

저의 접근 방식은 Jobject 또는 respandobject를 사용하지 않고 신경에 직접 필사적으로 표시됩니다. 이 코드는 기본적으로 json.net sourcecode에있는 expandoobjectconverter 클래스에서 복사되지만 expandoobject 대신 idictionary를 사용하는 변환기를 사용합니다.

용법:

var settings = new JsonSerializerSettings()
{
    Converters = { new DictionaryConverter() },
};
var result = JsonConvert.DeserializeObject<IDictionary<string, object>>(json, settings);

암호:

// based on ExpandoObjectConverter, but using arrays instead of IList, to behave similar to System.Web.Script.Serialization.JavaScriptSerializer
public class DictionaryConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return ReadValue(reader);
    }

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(IDictionary<string, object>));
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    private object ReadValue(JsonReader reader)
    {
        while (reader.TokenType == JsonToken.Comment)
        {
            if (!reader.Read())
                throw JsonSerializationExceptionCreate(reader, "Unexpected end when reading IDictionary<string, object>.");
        }

        switch (reader.TokenType)
        {
            case JsonToken.StartObject:
                return ReadObject(reader);
            case JsonToken.StartArray:
                return ReadList(reader);
            default:
                if (IsPrimitiveToken(reader.TokenType))
                    return reader.Value;

                throw JsonSerializationExceptionCreate(reader, string.Format(CultureInfo.InvariantCulture, "Unexpected token when converting IDictionary<string, object>: {0}", reader.TokenType));
        }
    }

    private object ReadList(JsonReader reader)
    {
        List<object> list = new List<object>();

        while (reader.Read())
        {
            switch (reader.TokenType)
            {
                case JsonToken.Comment:
                    break;
                default:
                    object v = ReadValue(reader);

                    list.Add(v);
                    break;
                case JsonToken.EndArray:
                    return list;
            }
        }

        throw JsonSerializationExceptionCreate(reader, "Unexpected end when reading IDictionary<string, object>.");
    }

    private object ReadObject(JsonReader reader)
    {
        IDictionary<string, object> dictionary = new Dictionary<string, object>();
        while (reader.Read())
        {
            switch (reader.TokenType)
            {
                case JsonToken.PropertyName:
                    string propertyName = reader.Value.ToString();

                    if (!reader.Read())
                        throw JsonSerializationExceptionCreate(reader, "Unexpected end when reading IDictionary<string, object>.");

                    object v = ReadValue(reader);

                    dictionary[propertyName] = v;
                    break;
                case JsonToken.Comment:
                    break;
                case JsonToken.EndObject:
                    return dictionary;
            }
        }

        throw JsonSerializationExceptionCreate(reader, "Unexpected end when reading IDictionary<string, object>.");
    }

    //based on internal Newtonsoft.Json.JsonReader.IsPrimitiveToken
    internal static bool IsPrimitiveToken(JsonToken token)
    {
        switch (token)
        {
            case JsonToken.Integer:
            case JsonToken.Float:
            case JsonToken.String:
            case JsonToken.Boolean:
            case JsonToken.Undefined:
            case JsonToken.Null:
            case JsonToken.Date:
            case JsonToken.Bytes:
                return true;
            default:
                return false;
        }
    }

    // based on internal Newtonsoft.Json.JsonSerializationException.Create
    private static JsonSerializationException JsonSerializationExceptionCreate(JsonReader reader, string message, Exception ex = null)
    {
        return JsonSerializationExceptionCreate(reader as IJsonLineInfo, reader.Path, message, ex);
    }

    // based on internal Newtonsoft.Json.JsonSerializationException.Create
    private static JsonSerializationException JsonSerializationExceptionCreate(IJsonLineInfo lineInfo, string path, string message, Exception ex)
    {
        message = JsonPositionFormatMessage(lineInfo, path, message);

        return new JsonSerializationException(message, ex);
    }

    // based on internal Newtonsoft.Json.JsonPosition.FormatMessage
    internal static string JsonPositionFormatMessage(IJsonLineInfo lineInfo, string path, string message)
    {
        if (!message.EndsWith(Environment.NewLine))
        {
            message = message.Trim();

            if (!message.EndsWith(".", StringComparison.Ordinal))
                message += ".";

            message += " ";
        }

        message += string.Format(CultureInfo.InvariantCulture, "Path '{0}'", path);

        if (lineInfo != null && lineInfo.HasLineInfo())
            message += string.Format(CultureInfo.InvariantCulture, ", line {0}, position {1}", lineInfo.LineNumber, lineInfo.LinePosition);

        message += ".";

        return message;
    }
}

게임에 조금 늦었지만 위의 솔루션 중 일부는 순수하고 간단한 .NET, JSON.NET 솔루션의 방향을 가리 켰습니다. 그래서 여기에는 매우 간단했습니다. 표준 .NET JSON 직렬화로 어떻게 수행되는지에 대한 전체 실행 예제 아래에서,이 예제는 루트 객체와 자식 물체 모두에 사전이 있습니다.

황금 총알은이 고양이입니다. 세트를 세리어 리저의 두 번째 매개 변수로 구문 분석합니다.

DataContractJsonSerializerSettings settings =
                       new DataContractJsonSerializerSettings();
                    settings.UseSimpleDictionaryFormat = true;

아래 전체 코드 :

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

    namespace Kipon.dk
    {
        public class JsonTest
        {
            public const string EXAMPLE = @"{
                ""id"": ""some id"",
                ""children"": {
                ""f1"": {
                    ""name"": ""name 1"",
                    ""subs"": {
                    ""1"": { ""name"": ""first sub"" },
                    ""2"": { ""name"": ""second sub"" }
                    }
                },
                ""f2"": {
                    ""name"": ""name 2"",
                    ""subs"": {
                    ""37"": { ""name"":  ""is 37 in key""}
                    }
                }
                }
            }
            ";

            [DataContract]
            public class Root
            {
                [DataMember(Name ="id")]
                public string Id { get; set; }

                [DataMember(Name = "children")]
                public Dictionary<string,Child> Children { get; set; }
            }

            [DataContract]
            public class Child
            {
                [DataMember(Name = "name")]
                public string Name { get; set; }

                [DataMember(Name = "subs")]
                public Dictionary<int, Sub> Subs { get; set; }
            }

            [DataContract]
            public class Sub
            {
                [DataMember(Name = "name")]
                public string Name { get; set; }
            }

            public static void Test()
            {
                var array = System.Text.Encoding.UTF8.GetBytes(EXAMPLE);
                using (var mem = new System.IO.MemoryStream(array))
                {
                    mem.Seek(0, System.IO.SeekOrigin.Begin);
                    DataContractJsonSerializerSettings settings =
                       new DataContractJsonSerializerSettings();
                    settings.UseSimpleDictionaryFormat = true;

                    var ser = new DataContractJsonSerializer(typeof(Root), settings);
                    var data = (Root)ser.ReadObject(mem);
                    Console.WriteLine(data.Id);
                    foreach (var childKey in data.Children.Keys)
                    {
                        var child = data.Children[childKey];
                        Console.WriteLine(" Child: " + childKey + " " + child.Name);
                        foreach (var subKey in child.Subs.Keys)
                        {
                            var sub = child.Subs[subKey];
                            Console.WriteLine("   Sub: " + subKey + " " + sub.Name);
                        }
                    }
                }
            }
        }
    }

짜증나게, 기본 모델 바인더를 사용하려면 양식 게시물과 같은 숫자 색인 값을 사용해야하는 것처럼 보입니다.

이 기사의 다음 발췌문을 참조하십시오 http://msdn.microsoft.com/en-us/magazine/hh781022.aspx:

다소 반 직관적이지만 JSON 요청은 동일한 요구 사항을 가지고 있습니다. 또한 이름 지정 구문 양식을 준수해야합니다. 예를 들어 이전 UnitPrice 컬렉션의 JSON 페이로드를 사용하십시오. 이 데이터의 순수한 JSON 배열 구문은 다음과 같이 표시됩니다.

[ 
  { "Code": "USD", "Amount": 100.00 },
  { "Code": "EUR", "Amount": 73.64 }
]

그러나 기본 값 공급자 및 모델 바인더는 데이터를 JSON 양식 게시물로 표시해야합니다.

{
  "UnitPrice[0].Code": "USD",
  "UnitPrice[0].Amount": 100.00,

  "UnitPrice[1].Code": "EUR",
  "UnitPrice[1].Amount": 73.64
}

복잡한 객체 수집 시나리오는 아마도 구문이 모든 개발자에게 반드시 명백하지 않기 때문에 개발자가 실행하는 가장 널리 문제가있는 시나리오 중 하나 일 것입니다. 그러나 복잡한 컬렉션을 게시하기위한 비교적 간단한 구문을 배우면 이러한 시나리오는 훨씬 쉽게 처리하기가 쉬워집니다.

당신은 사용할 수 있습니다 Tiny-Json

string json = "{\"key1\":\"value1\", \"key2\":\"value2\"}";
IDictionary<string, string> dict = Tiny.Json.Decode<Dictionary<string, string>>(json);

사용하는 것이 좋습니다 System.Runtime.Serialization.Json 그것은 .NET 4.5의 일부입니다.

[DataContract]
public class Foo
{
   [DataMember(Name = "data")]
   public Dictionary<string,string> Data { get; set; }
}

그런 다음 다음과 같이 사용하십시오.

var serializer = new DataContractJsonSerializer(typeof(List<Foo>));
var jsonParams = @"{""data"": [{""Key"":""foo"",""Value"":""bar""}] }";
var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonParams));

var obj = serializer.ReadObject(stream);
Console.WriteLine(obj);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top