将具有未知值类型的字典转换为json

时间:2014-12-22 20:33:43

标签: c#

我编写了下面的代码,将字典转换为json字符串。 这里的问题是字典值可以是各种类型 string,int,string [],int [],float [],... 我尝试使用泛型,但是我得到一个编译错误,我在其中执行GetParamList,因为它希望我指定实际类型。 我想知道是否有办法可以避免使用大量的if / else条件来实现我想要的目标。

private static string GetParamList<T>(object values)
{
    if (values.GetType().Equals(typeof(string[])) )
    {
        string[] res = (string[])values;
        if (values.GetType().Equals(typeof(string[])))
        {
            for (int i = 0; i < res.Length; i++)
            {
                if (!res[i].ToString().StartsWith("\""))
                {
                    res[i] = string.Format("\"{0}\"", res[i]);
                }
            }
        }
        return string.Join(",", res);
    }
    else if (values.GetType().Equals(typeof(string)))
    {
        return string.Format("\"{0}\"", values);
    }
    else// array of numbers:
    {
        string[] res = ((T[])values).Select(x => x.ToString()).ToArray<string>();
        return string.Join(",", res);
    }
}

private static string dictToJson(Dictionary<string, object> data)
{
    List<string> entries = new List<string>();
    foreach (var entry in data)
    {
        Type T = entry.Value.GetType();
        entries.Add(string.Format("\"{0}\": {1}", entry.Key, GetParamList<T>(entry.Value)));
    }
    return "{" + string.Join(",", entries.ToArray<string>()) + "}";
}

3 个答案:

答案 0 :(得分:1)

这里犯了错误:

Type T = entry.Value.GetType();

您在此处所做的是获取通用参数 - 相反,您将获得表示所需参数的类Type的对象。泛型设计用于在编译时使用已知类型,因此JIT编译器可以为您动态创建类的定义。因此,您无法将Type对象作为通用参数传递。

然而,有几种方法可以解决这个问题。

第一个也是最简单的方法是使用可以执行通用推理的工厂方法,并将通用参数作为dynamic传递。这将强制CLR延迟到运行时以决定使用哪种类型,然后使用最匹配的类型作为参数。并非按原样使用您的代码 - 泛型推理要求您使用T作为参数类型以及泛型类型,例如:

private static string GetParamList<T>(T[] values)

第二种方法是对操作进行元代码并使用System.Linq.Expressions命名空间编译调用,这可能会更加详细:

var val = Expression.Constant(entry.Value);
var method = typeof(MyType)    // Where MyType is the type containing "GetParamList"
    .GetMethod("GetParamList")
    .MakeGenericMethod(t);     // Where t is the desired type
string result = Expression
    // Lambda turns an expression tree into an expressiong tree with an explicit delegate signature
    .Lambda<Func<String>>(
        Expression.Call(null, method, val))    // "Call the method against nothing (it's static) and pass in val (which is a constant in this case)"
    .Compile()  // This compiles our expression tree
    .Invoke();  // Run the method

答案 1 :(得分:0)

你正在努力学习,试试这个。

public List<Event_Log> GetAll()
{
 List<Event_Log> result = new List<Event_Log>();
    //add result collection here...
   return result;
}

答案 2 :(得分:0)

感谢您推荐&#34; Newtonsoft.Json&#34;。 我以这种方式使用了这个包,所有的问题都解决了:

private static string dictToJson(Dictionary<string, object> data)
{

    string json = JsonConvert.SerializeObject(data, Formatting.None, new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.None,
        TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
    });

    return json;
}