我有以下代码:

var user = (Dictionary<string, object>)serializer.DeserializeObject(responsecontent);

responsecontent中的输入是JSON,但它没有正确地反序列化为对象。我应该如何正确地反序列化它?


当前回答

系统。Json现在工作了…

安装 nuget https://www.nuget.org/packages/System.Json

PM> Install-Package System.Json -Version 4.5.0

示例:

// PM>Install-Package System.Json -Version 4.5.0

using System;
using System.Json;

namespace NetCoreTestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Note that JSON keys are case sensitive, a is not same as A.

            // JSON Sample
            string jsonString = "{\"a\": 1,\"b\": \"string value\",\"c\":[{\"Value\": 1}, {\"Value\": 2,\"SubObject\":[{\"SubValue\":3}]}]}";

            // You can use the following line in a beautifier/JSON formatted for better view
            // {"a": 1,"b": "string value","c":[{"Value": 1}, {"Value": 2,"SubObject":[{"SubValue":3}]}]}

            /* Formatted jsonString for viewing purposes:
            {
               "a":1,
               "b":"string value",
               "c":[
                  {
                     "Value":1
                  },
                  {
                     "Value":2,
                     "SubObject":[
                        {
                           "SubValue":3
                        }
                     ]
                  }
               ]
            }
            */

            // Verify your JSON if you get any errors here
            JsonValue json = JsonValue.Parse(jsonString);

            // int test
            if (json.ContainsKey("a"))
            {
                int a = json["a"]; // type already set to int
                Console.WriteLine("json[\"a\"]" + " = " + a);
            }

            // string test
            if (json.ContainsKey("b"))
            {
                string b = json["b"];  // type already set to string
                Console.WriteLine("json[\"b\"]" + " = " + b);
            }

            // object array test
            if (json.ContainsKey("c") && json["c"].JsonType == JsonType.Array)
            {
                // foreach loop test
                foreach (JsonValue j in json["c"])
                {
                    Console.WriteLine("j[\"Value\"]" + " = " + j["Value"].ToString());
                }

                // multi level key test
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][0]["Value"].ToString());
                Console.WriteLine("json[\"c\"][0][\"Value\"]" + " = " + json["c"][1]["Value"].ToString());
                Console.WriteLine("json[\"c\"][1][\"SubObject\"][0][\"SubValue\"]" + " = " + json["c"][1]["SubObject"][0]["SubValue"].ToString());
            }

            Console.WriteLine();
            Console.Write("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

其他回答

试试下面的代码:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
JArray array = new JArray();
using (var twitpicResponse = (HttpWebResponse)request.GetResponse())
using (var reader = new StreamReader(twitpicResponse.GetResponseStream()))
{
    JavaScriptSerializer js = new JavaScriptSerializer();
    var objText = reader.ReadToEnd();

    JObject joResponse = JObject.Parse(objText);
    JObject result = (JObject)joResponse["result"];
    array = (JArray)result["Detail"];
    string statu = array[0]["dlrStat"].ToString();
}

您可以使用以下扩展

public static class JsonExtensions
{
    public static T ToObject<T>(this string jsonText)
    {
        return JsonConvert.DeserializeObject<T>(jsonText);
    }

    public static string ToJson<T>(this T obj)
    {
        return JsonConvert.SerializeObject(obj);
    } 
}

我最终创建了一个简单的类,可以动态地创建类型,实例化它们并将它们水合物化,镜像输入JSON的结构。

你可以在这里找到它:

https://github.com/starnutoditopo/JsonToObject

JsonToObjectConverter.cs

using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Text.Json;

namespace JsonToObject;

/// <summary>Provides functionalities to convert JSON strings in to CLR objects.</summary>
public class JsonToObjectConverter
{
    private class Counter
    {
        private ulong count;
        public Counter()
        {
            this.count = 0;
        }

        public ulong Next()
        {
            this.count++;
            return this.count;
        }
    }


    private static ulong assemblyGenerationCounter;
    private readonly JsonToObjectConverterOptions options;

    static JsonToObjectConverter()
    {
        assemblyGenerationCounter = 0;
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="JsonToObjectConverter" /> class, using default options.
    /// </summary>
    /// <param name="options">The options.</param>
    public JsonToObjectConverter()
        : this(new JsonToObjectConverterOptions())
    {
    }


    /// <summary>
    /// Initializes a new instance of the <see cref="JsonToObjectConverter" /> class, using the specified options.
    /// </summary>
    /// <param name="options">The options.</param>
    public JsonToObjectConverter(JsonToObjectConverterOptions options)
    {
        this.options = options;
    }

    /// <summary>Converts a JSON string to an instance of a CLR object.</summary>
    /// <param name="jsonString">The json string.</param>
    /// <returns>
    ///   <br />
    /// </returns>
    public object? ConvertToObject(string jsonString)
    {
        JsonSerializerOptions opt = new JsonSerializerOptions()
        {
            PropertyNameCaseInsensitive = true
        };
        JsonElement rawResult = JsonSerializer.Deserialize<JsonElement>(jsonString, opt);
        object? result = ToStronglyTypedObject(rawResult);
        return result;
    }

    private object? ToStronglyTypedObject(JsonElement? nullableJsonElement)
    {
        string assemblyNameString;
        ulong assemblyId = Interlocked.Increment(ref assemblyGenerationCounter);
        try
        {
            assemblyNameString = string.Format(this.options.RuntimeGeneratedAssemblyNameTemplate, assemblyId.ToString(CultureInfo.InvariantCulture));
        }
        catch
        {
            throw new InvalidOperationException($@"Unable to generate assembly name using template '{this.options.RuntimeGeneratedAssemblyNameTemplate}' and id '{assemblyId}'. Please, review the {nameof(JsonToObjectConverterOptions.RuntimeGeneratedAssemblyNameTemplate)} property in the options.");
        }
        ModuleBuilder moduleBuilder = CreateModuleBuilder(assemblyNameString, this.options.RuntimeGeneratedModuleName);
        Counter typeGenerationCounter = new Counter();
        var result = ToStronglyTypedObject(nullableJsonElement, moduleBuilder, typeGenerationCounter);
        return result;
    }
    private object? ToStronglyTypedObject(
        JsonElement? nullableJsonElement,
        ModuleBuilder moduleBuilder,
        Counter typeGenerationCounter
    )
    {
        if (nullableJsonElement == null)
        {
            return null;
        }

        JsonElement jsonElement = nullableJsonElement.Value;

        switch (jsonElement.ValueKind)
        {
            case JsonValueKind.Undefined:
                return null;
            case JsonValueKind.String:
                return jsonElement.GetString();
            case JsonValueKind.False:
                return false;
            case JsonValueKind.True:
                return true;
            case JsonValueKind.Null:
                return null;
            case JsonValueKind.Number:
                {
                    if (jsonElement.TryGetDouble(out var result))
                    {
                        return result;
                    }
                }
                throw new InvalidOperationException($"Unable to parse {jsonElement} as number.");
            case JsonValueKind.Object:
                {
                    ulong typeId = typeGenerationCounter.Next();
                    string typeName;
                    try
                    {
                        typeName = string.Format(this.options.RuntimeGeneratedTypeNameTemplate, typeId.ToString(CultureInfo.InvariantCulture));
                    }
                    catch
                    {
                        throw new InvalidOperationException($@"Unable to generate type name using template '{this.options.RuntimeGeneratedTypeNameTemplate}' and id '{typeId}'. Please, review the {nameof(JsonToObjectConverterOptions.RuntimeGeneratedTypeNameTemplate)} property in the options.");
                    }

                    TypeBuilder typeBuilder = CreateTypeBuilder(moduleBuilder, typeName);
                    Dictionary<string, object?> propertyValues = new Dictionary<string, object?>();
                    foreach (var property in jsonElement.EnumerateObject())
                    {
                        string propertyName = property.Name;
                        object? propertyValue = ToStronglyTypedObject(property.Value, moduleBuilder, typeGenerationCounter);
                        Type propertyValueType;
                        if (null == propertyValue)
                        {
                            propertyValueType = typeof(object);
                        }
                        else
                        {
                            propertyValueType = propertyValue.GetType();
                        }
                        CreateAutoImplementedProperty(typeBuilder, propertyName, propertyValueType);
                        propertyValues.Add(propertyName, propertyValue);
                    }

                    Type resultType = typeBuilder.CreateType()!;
                    object result = Activator.CreateInstance(resultType)!;
                    foreach (var pair in propertyValues)
                    {
                        var propertyInfo = resultType.GetProperty(pair.Key)!;
                        propertyInfo.SetValue(result, pair.Value);
                    }
                    return result;
                }
            case JsonValueKind.Array:
                {
                    List<object?> list = new List<object?>();
                    foreach (var item in jsonElement.EnumerateArray())
                    {
                        object? value = ToStronglyTypedObject(item, moduleBuilder, typeGenerationCounter);
                        list.Add(value);
                    }
                    return list.ToArray();
                }
            default:
                throw new InvalidOperationException($"Value type '{jsonElement.ValueKind}' is not supported");
        }
    }

    private static ModuleBuilder CreateModuleBuilder(
            string assemblyNameString,
            string moduleName
        )
    {
        // create assembly name
        var assemblyName = new AssemblyName(assemblyNameString);
        // create the assembly builder
        AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

        // create the module builder
        ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
        return moduleBuilder;
    }

    private static TypeBuilder CreateTypeBuilder(
            ModuleBuilder moduleBuilder,
            string typeName
        )
    {
        // create the type builder
        TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
        typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
        return typeBuilder;
    }

    private static void CreateAutoImplementedProperty(
        TypeBuilder builder,
        string propertyName,
        Type propertyType
        )
    {
        const string PrivateFieldPrefix = "m_";
        const string GetterPrefix = "get_";
        const string SetterPrefix = "set_";

        // Generate the field.
        FieldBuilder fieldBuilder = builder.DefineField(
            string.Concat(PrivateFieldPrefix, propertyName),
                          propertyType, FieldAttributes.Private);

        // Generate the property
        PropertyBuilder propertyBuilder = builder.DefineProperty(
            propertyName, PropertyAttributes.HasDefault, propertyType, null);

        // Property getter and setter attributes.
        MethodAttributes propertyMethodAttributes =
            MethodAttributes.Public | MethodAttributes.SpecialName |
            MethodAttributes.HideBySig;

        // Define the getter method.
        MethodBuilder getterMethod = builder.DefineMethod(
            string.Concat(GetterPrefix, propertyName),
            propertyMethodAttributes, propertyType, Type.EmptyTypes);

        // Emit the IL code.
        // ldarg.0
        // ldfld,_field
        // ret
        ILGenerator getterILCode = getterMethod.GetILGenerator();
        getterILCode.Emit(OpCodes.Ldarg_0);
        getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
        getterILCode.Emit(OpCodes.Ret);

        // Define the setter method.
        MethodBuilder setterMethod = builder.DefineMethod(
            string.Concat(SetterPrefix, propertyName),
            propertyMethodAttributes, null, new Type[] { propertyType });

        // Emit the IL code.
        // ldarg.0
        // ldarg.1
        // stfld,_field
        // ret
        ILGenerator setterILCode = setterMethod.GetILGenerator();
        setterILCode.Emit(OpCodes.Ldarg_0);
        setterILCode.Emit(OpCodes.Ldarg_1);
        setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
        setterILCode.Emit(OpCodes.Ret);

        propertyBuilder.SetGetMethod(getterMethod);
        propertyBuilder.SetSetMethod(setterMethod);
    }
}

JsonToObjectConverterOptions.cs

namespace JsonToObject;

/// <summary>
/// Defines the options to instantiate a <see cref="JsonToObjectConverter" /> object.
/// </summary>
public class JsonToObjectConverterOptions
{
    private const string CONSTANTS_RuntimeGeneratedModuleName = $"RuntimeGeneratedModule";
    private const string CONSTANTS_RuntimeGeneratedAssemblyNameTemplate = "RuntimeGeneratedAssembly_{0}";
    private const string CONSTANTS_RuntimeGeneratedTypeNameTemplate = "RuntimeGeneratedType_{0}";

    /// <summary>Gets or sets the name of the runtime-generated module.</summary>
    /// <value>The name of the runtime-generated module.</value>
    public string RuntimeGeneratedModuleName { get; set; } = CONSTANTS_RuntimeGeneratedModuleName;

    /// <summary>Gets or sets the template to use to generate the name of runtime-generated assemblies.</summary>
    /// <value>The template to use to generate the name of runtime-generated assemblies.</value>
    /// <remarks>Should contain a "{0}" placeholder.</remarks>
    public string RuntimeGeneratedAssemblyNameTemplate { get; set; } = CONSTANTS_RuntimeGeneratedAssemblyNameTemplate;

    /// <summary>Gets or sets the template to use to generate the name of runtime-generated types.</summary>
    /// <value>The template to use to generate the name of runtime-generated types.</value>
    /// <remarks>Should contain a "{0}" placeholder.</remarks>
    public string RuntimeGeneratedTypeNameTemplate { get; set; } = CONSTANTS_RuntimeGeneratedTypeNameTemplate;
}

如果您可以使用。net 4,请查看:http://visitmix.com/writings/the-rise-of-json (archive.org)

以下是该网站的一个片段:

WebClient webClient = new WebClient();
dynamic result = JsonValue.Parse(webClient.DownloadString("https://api.foursquare.com/v2/users/self?oauth_token=XXXXXXX"));
Console.WriteLine(result.response.user.firstName);

最后一个控制台。WriteLine很贴心…

正如这里的回答-反序列化JSON到c#动态对象?

使用Json非常简单。NET:

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

或者使用Newtonsoft.Json.Linq:

dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;