简体   繁体   English

使用C#如何将动态生成的集合列表作为JSON数组传递给WCF Web服务

[英]With C# how to pass list of dynamically generated collection as JSON array to WCF web service

My objective: To create a list of objects with dynamically generated properties which can be passed to WCF service parameter as a JSON array. 我的目标:创建具有动态生成属性的对象列表,这些属性可以作为JSON数组传递给WCF服务参数。

Final outcome is the following: 最终结果如下:

[{id:2, name:"John", country:"Germany"},...] or [{id:2, name:"John", country:"Germany"},...]

[{id:3, city:"Sydney"},...]

From WCF I don't have the convenience of working with a class, ie "Thing" so I could do this: 从WCF中,我没有使用类(即“事物”)的便利,因此我可以这样做:

public List<Thing> MyThings {get; set;}

I do not know what the properties are at run time. 我不知道这些属性在运行时。 I have experimented with System.Dynamic namespace using 我已经尝试使用System.Dynamic命名空间

List<ExpandoObject>

Unfortunately, dynamic code will give me the error message: 不幸的是,动态代码会给我错误信息:

Dynamic operations can only be performed in homogenous AppDomain. 动态操作只能在同构的AppDomain中执行。

To allow dynamic code to run I would have to change legacyCasModel tag in the web.config. 为了运行动态代码,我必须在web.config中更改legacyCasModel标记。 Unfortunately I cannot change the web.config. 不幸的是,我无法更改web.config。

Another option is to use Dictionary array but I do not want the key/value pair format: 另一个选择是使用Dictionary数组,但我不希望键/值对格式:

[{key:id}, {value:2}] 

for I'm interested in 因为我对

[{id:2, name:"John"}]

My challenge is that I don't know what the properties are at run time otherwise it would be easy to convert a List<T> to array. 我的挑战是我不知道运行时的属性,否则将List<T>转换为数组很容易。

Any suggestion? 有什么建议吗?

To pass list of dynamically generated collection as JSON array to WCF web service, you can use ExpandoObject and any serializer, I have used Newtonsoft.Json 要将动态生成的集合的列表作为JSON数组传递到WCF Web服务,可以使用ExpandoObject和任何序列化程序,我已经使用Newtonsoft.Json

dynamic obj1 = new ExpandoObject();
obj1.id = 1;
obj1.name = "TPS";

dynamic obj2 = new ExpandoObject();
obj2.id = 2;
obj2.name = "TPS_TPS";

var Objects = new List<ExpandoObject>();
Objects.Add(flexible);
Objects.Add(flexible2);

var serialized = JsonConvert.SerializeObject(l); // JsonConvert - from Newtonsoft.Json

To Deserialize and retrieve the object dynamically i have used JavaScriptSerializer, you can also use System.Web.Helpers.Json.Decode() 若要动态反序列化和检索对象,我已经使用JavaScriptSerializer,也可以使用System.Web.Helpers.Json.Decode()

All you need is this code and reference to a System.Web.Extensions from your project : 您所需要做的就是这段代码,并引用您项目中的System.Web.Extensions:

public sealed class DynamicJsonConverter : JavaScriptConverter
{
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        if (dictionary == null)
            throw new ArgumentNullException("dictionary");

        return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IEnumerable<Type> SupportedTypes
    {
        get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
    }

    #region Nested type: DynamicJsonObject

    private sealed class DynamicJsonObject : DynamicObject
    {
        public readonly IDictionary<string, object> _dictionary;

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

        public override string ToString()
        {
            var sb = new StringBuilder("{");
            ToString(sb);
            return sb.ToString();
        }

        private void ToString(StringBuilder sb)
        {
            var firstInDictionary = true;
            foreach (var pair in _dictionary)
            {
                if (!firstInDictionary)
                    sb.Append(",");
                firstInDictionary = false;
                var value = pair.Value;
                var name = pair.Key;
                if (value is string)
                {
                    sb.AppendFormat("{0}:\"{1}\"", name, value);
                }
                else if (value is IDictionary<string, object>)
                {
                    new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);
                }
                else if (value is ArrayList)
                {
                    sb.Append(name + ":[");
                    var firstInArray = true;
                    foreach (var arrayValue in (ArrayList)value)
                    {
                        if (!firstInArray)
                            sb.Append(",");
                        firstInArray = false;
                        if (arrayValue is IDictionary<string, object>)
                            new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);
                        else if (arrayValue is string)
                            sb.AppendFormat("\"{0}\"", arrayValue);
                        else
                            sb.AppendFormat("{0}", arrayValue);

                    }
                    sb.Append("]");
                }
                else
                {
                    sb.AppendFormat("{0}:{1}", name, value);
                }
            }
            sb.Append("}");
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (!_dictionary.TryGetValue(binder.Name, out result))
            {
                // return null to avoid exception.  caller can check for null this way...
                result = null;
                return true;
            }

            result = WrapResultObject(result);
            return true;
        }

        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        {
            if (indexes.Length == 1 && indexes[0] != null)
            {
                if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))
                {
                    // return null to avoid exception.  caller can check for null this way...
                    result = null;
                    return true;
                }

                result = WrapResultObject(result);
                return true;
            }

            return base.TryGetIndex(binder, indexes, out result);
        }

        private static object WrapResultObject(object result)
        {
            var dictionary = result as IDictionary<string, object>;
            if (dictionary != null)
                return new DynamicJsonObject(dictionary);

            var arrayList = result as ArrayList;
            if (arrayList != null && arrayList.Count > 0)
            {
                return arrayList[0] is IDictionary<string, object>
                    ? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)))
                    : new List<object>(arrayList.Cast<object>());
            }

            return result;
        }
    }

    #endregion
}

How to Use : 如何使用 :

string jsonString = ".......";

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic data = serializer.Deserialize(jsonString, typeof(object));

foreach (var d in data)
{
    var id = d.id;
    var name = d.name;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM