How can I deserialize JSON to a simple Dictionary in ASP.NET?

前端 未结 21 2757
粉色の甜心
粉色の甜心 2020-11-21 06:33

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

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

21条回答
  •  迷失自我
    2020-11-21 07:25

    My approach directly deserializes to IDictionary, without JObject or ExpandObject in between. The code uses converter, which is basically copied from ExpandoObjectConverter class found in JSON.NET sourcecode, but using IDictionary instead of ExpandoObject.

    Usage:

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

    Code:

    // 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));
        }
    
        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.");
            }
    
            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: {0}", reader.TokenType));
            }
        }
    
        private object ReadList(JsonReader reader)
        {
            List list = new List();
    
            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.");
        }
    
        private object ReadObject(JsonReader reader)
        {
            IDictionary dictionary = new Dictionary();
            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.");
    
                        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.");
        }
    
        //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;
        }
    }
    
        

    提交回复
    热议问题