C#向下转换要映射的对象类型

时间:2015-03-11 14:52:33

标签: c# json

我使用JavaScriptSerializer将json字符串序列化为特定的Class

这是原点json字符串:

{
   "status":0,
   "data":[
          {
             "username":"yong6180212856@163.com",
             "password":"r2166745"
          }, 
          {
             "username":"xinnai1122139@163.com",
             "password":"f0341303"
          }
          ],
   "msg":"OK"
}

这是来自http服务器的结构化响应,data字段将因不同请求而异。因此,在RetData课程中,我不想制作固定类型的data并只使用Object,然后在需要时向下转换为相应的类型。

 class RetData {
    public int status {get;set;}
    public string msg {get;set;}
    public List<Object> data {get;set;}
 }

使用后

 RetData retData = new JavaScriptSerializer<RetData>(jsonStr);

然后我想要像这样检索每个密码:

foreach (var item in retData.data){
   // some thing like this but I really don't know which type 
   // should I downcast to here.
   //                  |
   //                  V
   string password = ((??map??)item).getString("password"); 
   Console.WriteLine(password);
}

正如你所看到的,我应该转向什么类型,检索password飞行,我熟悉Java但是C#的新手,需要一些帮助。

3 个答案:

答案 0 :(得分:0)

这里有很多方法。从您到达的最短路径是将RetData更改为:

public class RetData
{
    public int status { get; set; }
    public string msg { get; set; }
    public List<Dictionary<object,object>> data { get; set; }
}

然后读取这样的数据:

RetData retData = (RetData)new JavaScriptSerializer().Deserialize(jsonStr, typeof(RetData));

foreach (var item in retData.data)
{
    string password = item["username"].ToString();
    Console.WriteLine(password);
}

限制是这实际上只适用于简单的名称/值对。另一种方法是改为使用Newtonsoft Json,而不是Microsoft Json。这有一个名为&#34; JObject&#34;它可以处理任何类型的Json数据。 Newtonsoft Json可作为nuget包使用。

我对动态的评论是错误的。我试过它,结果证明.NET序列化程序不了解动态或ExpandoObject。 : - (

答案 1 :(得分:0)

当您使用JavaScriptSerializer将JSON反序列化为object属性或字段时,序列化程序将以递归方式选择要对其中的每个JSON元素进行反序列化的最合适的表示形式:

这允许反序列化和使用完全通用的JSON数据。

有助于使用来自JavaScriptSerializer的无类型反序列化JSON的一些扩展方法包括:

public static class JavaScriptSerializerObjectExtensions
{
    public static object JsonElementAt(this object obj, int index)
    {
        if (index < 0)
            throw new ArgumentException();
        var array = obj as object[];
        if (array == null || index >= array.Length)
            return null;
        return array[index];
    }

    public static object JsonPropertyAt(this object obj, string name)
    {
        var dict = obj as IDictionary<string, object>;
        if (dict == null)
            return null;
        object value;
        if (!dict.TryGetValue(name, out value))
            return null;
        return value;
    }

    public static bool IsJsonArray(this object obj)
    {
        return obj is object[];
    }

    public static object [] AsJsonArray(this object obj)
    {
        return obj as object[];
    }

    public static bool IsJsonObject(this object obj)
    {
        return obj is IDictionary<string, object>;
    }

    public static IDictionary<string, object> AsJsonObject(this object obj)
    {
        return obj as IDictionary<string, object>;
    }

    public static bool IsJsonNumber(this object obj)
    {
        if (obj == null)
            return false;
        switch (Type.GetTypeCode(obj.GetType()))
        {
            case TypeCode.Int32:
            case TypeCode.Int64:
            case TypeCode.Decimal:
            case TypeCode.Double:
                return true;

            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
            case TypeCode.Int16:
            case TypeCode.Single:
                Debug.WriteLine("Unexpected integer type " + Type.GetTypeCode(obj.GetType()));
                return true;

            default:
                return false;
        }
    }

    public static bool IsJsonBoolean(this object obj)
    {
        return obj is bool;
    }

    public static bool IsJsonString(this object obj)
    {
        return obj is string;
    }

    public static bool IsDateTime(this object obj)
    {
        return obj is DateTime;
    }

    [Conditional("DEBUG")]
    public static void DebugWriteJson(this object obj)
    {
        var sb = obj.DumpJson();
        Debug.WriteLine(sb);
    }

    public static string DumpJson(this object obj)
    {
        var sb = obj.DumpJson(new StringBuilder(), 0, false, string.Empty);
        return sb.ToString();
    }

    static StringBuilder DumpJson(this object obj, StringBuilder sb, int level, bool isPropertyValue, string postfix)
    {
        if (obj == null)
            return sb;
        string prefix = new string(' ', 2 * level);
        if (obj is IList<object>)
        {
            var array = (IList<object>)obj;
            if (isPropertyValue)
                sb.AppendLine();
            sb.AppendLine(prefix + "[");
            for (int i = 0; i < array.Count; i++)
            {
                array[i].DumpJson(sb, level + 1, false, (i == array.Count - 1 ? string.Empty : ","));
            }
            sb.AppendLine(prefix + "]" + postfix);
        }
        else if (obj is IDictionary<string, object>)
        {
            if (isPropertyValue)
                sb.AppendLine();
            sb.AppendLine(prefix + "{");
            var dict = ((IDictionary<string, object>)obj).ToList();
            for (int i = 0; i < dict.Count; i++)
            {
                sb.AppendFormat("{0}  \"{1}\" : ", prefix, dict[i].Key);
                dict[i].Value.DumpJson(sb, level + 2, true, (i == dict.Count - 1 ? string.Empty : ","));
            }
            sb.AppendLine(prefix + "}" + postfix);
        }
        else if (obj.IsJsonString())
        {
            string initialPrefix = (isPropertyValue ? "" : prefix);
            sb.AppendLine(initialPrefix + '"' + obj.ToString() + '"' + postfix);
        }
        else
        {
            string initialPrefix = (isPropertyValue ? "" : prefix);
            sb.AppendLine(initialPrefix + obj.ToString().ToLower() + postfix);
        }
        return sb;
    }

然后你可以这样做:

class RetData
{
    public int status { get; set; }
    public string msg { get; set; }
    public object data { get; set; }
}

        var retData = (new JavaScriptSerializer()).Deserialize<RetData>(jsonStr);

        if (retData.data.IsJsonArray())
            foreach (var obj in retData.data.AsJsonArray())
                if (obj.JsonPropertyAt("username") != null)
                    Console.WriteLine(obj.JsonPropertyAt("password"));

或者,如果它看起来更熟悉:

        if (retData.data.IsJsonArray())
            foreach (var obj in retData.data.AsJsonArray())
                if (obj.IsJsonObject())
                {
                    var map = obj.AsJsonObject();
                    if (map.ContainsKey("username") && map.ContainsKey("password"))
                        Console.WriteLine(map["password"]);
                }

然而,老实说,这已接近重新发明Linq-to-Json,因此您可能需要调查切换到Json.NET

答案 2 :(得分:-1)

使用dynamic关键字来定义data的类型:

class RetData
{
    public int status { get; set; }
    public string msg { get; set; }
    public dynamic data { get; set; }
}

请注意,这将取消智能感知和编译验证,这意味着检查类型的责任是你的。

或者,通过更多有关您的设计的详细信息,您可以创建基础数据类,而不是为不同的数据类型继承和实现它。