我使用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#的新手,需要一些帮助。
答案 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元素进行反序列化的最合适的表示形式:
Dictionary<string, System.Object>
System.Object []
string
。bool
。int
,long
,decimal
或double
。DateTime
。这允许反序列化和使用完全通用的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; }
}
请注意,这将取消智能感知和编译验证,这意味着检查类型的责任是你的。
或者,通过更多有关您的设计的详细信息,您可以创建基础数据类,而不是为不同的数据类型继承和实现它。