6

我得到一个 JSON 对象(可能包含多个级别的 JSON 数组等),我想将其转换为 ExpandoObject。

我想出了如何在运行时向 ExpandoObject 添加简单属性,因为它实现了 IDictionary,但是如何在运行时添加嵌套属性(例如,类似的东西myexpando.somelist.anotherlist.someitem)才能正确解析?

编辑:目前这适用于简单的(第一级)属性:

var exo = new ExpandoObject() as IDictionary<String, Object>;
exo.Add(name, value);

问题是如何获得要嵌套的名称以及如何相应地解析 ExpandoObject。

4

4 回答 4

8
dynamic myexpando = new ExpandoObject();
myexpando.somelist = new ExpandoObject() as dynamic;
myexpando.somelist.anotherlist = new ExpandoObject() as dynamic;
myexpando.somelist.anotherlist.someitem = "Hey Hey There! I'm a nested value :D";
于 2014-07-09T06:59:17.223 回答
1

您可以通过在TryGetValue调用时存储对先前检索到的对象或字典的引用来做到这一点。我使用如下所示的类:

public DynamicFile(IDictionary<string, object> dictionary)
{
    if (dictionary == null)
        throw new ArgumentNullException("dictionary");
    _dictionary = dictionary;
    _lastGetRef = _dictionary;
}

private readonly IDictionary<string, object> _dictionary;
private IDictionary<string, object> _lastGetRef;

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
    if (!_dictionary.TryGetValue(binder.Name, out result))
    {
        result = null;
        return true;
    }

    var dictionary = result as IDictionary<string, object>;
    if (dictionary != null)
    {
        result = new DynamicFile(dictionary);
        _lastGetRef = dictionary;
        return true;
    }

    return true;
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
    if(_dictionary.ContainsKey(binder.Name))
        _dictionary[binder.Name] = value;
    else if (_lastGetRef.ContainsKey(binder.Name))
        _lastGetRef[binder.Name] = value;
    else
        _lastGetRef.Add(binder.Name, value);

    return true;
}

_dictionary由构造函数在创建动态对象时设置,然后设置为直接最后一个引用字典。这是因为字典是类,因此是引用类型。

为了正确嵌套,您需要在每个嵌套级别实例化每个字典,就像多维数组一样。例如:

myexpando.somelist = new Dictionary<string, object>();
myexpando.somelist.anotherlist = new Dictionary<string, object>();
myexpando.somelist.anotherlist.someitem = "Hey Hey There! I'm a nested value :D";

您可能可以编写一些代码,TryGetMember当密钥不存在时自动添加字典,但我不需要,所以我没有添加它。

于 2012-12-22T07:21:34.760 回答
1

这样做怎么样:

var exo = new ExpandoObject() as IDictionary<String, Object>;
var nested1 = new ExpandoObject() as IDictionary<String, Object>;

exo.Add("Nested1", nested1);
nested1.Add("Nested2", "value");

dynamic d = exo;
Console.WriteLine(d.Nested1.Nested2); // Outputs "value"
于 2012-11-30T22:29:30.367 回答
0

很容易

扩大

public static class ObjectExtension
{
    public static ExpandoObject ToExpando(this object source)
    {
        IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(source);

        IDictionary<string, object> expando = new ExpandoObject();

        foreach (var item in anonymousDictionary)
            expando.Add(item);

        return (ExpandoObject)expando;
    }
}

客户行动

    public IActionResult Client(string username)
    {
        var client = HttpContext.Items["profile"] as Client;

        var model = new
        {
            client.Id,
            client.Name,
            client.Surname,
            client.Username,
            client.Photo,
            CoverPhoto = new {
               client.CoverPhoto.Source,
               client.CoverPhoto.X
            }.ToExpando(),
        }.ToExpando();

        return View(model);
    }

客户端.cshtml

<img id="cover-photo" src="@Model.CoverPhoto.Source" />
于 2018-06-01T06:23:06.497 回答