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

本文关键字:字典 转换 JSON 类型 未知 | 更新日期: 2023-09-27 18:34:55

我编写了下面的代码来将字典转换为 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>()) + "}";
}

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

错误在这里犯:

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

你正在以艰难的方式做到这一点,试试这个。

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

感谢您推荐"Newtonsoft.Json"。我以这种方式使用该包,所有问题都解决了:

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;
}