【问题标题】:Deserialize JSON.NET not knowing the type [duplicate]在不知道类型的情况下反序列化 JSON.NET [重复]
【发布时间】:2018-01-11 17:42:50
【问题描述】:

所以我正在编写一个 tcp/ip 聊天,我想使用 json.net 来序列化消息,以便我可以通过网络发送它。

我收到了这两种类型的消息:

class AlertMessage
{
    public string Client { get; set; }
    public ServerManager.Status Status { get; set; } //enum {Connect, Disconnect}
}

class TextMessage
{
    public string Client { get; set; }
    public string Message { get; set; }
}

要反序列化我需要使用JsonConvert.DeserializeObject<T>(object)的方法,但是在客户端我不能真正告诉什么类型到达,欢迎任何帮助!谢谢

【问题讨论】:

  • 反序列化为更通用的类,如class Message { public string Client { get; set; } public ServerManager.Status Status { get; set; } public string Message { get; set; } } 现在您可以测试属性并相应地使用
  • 我会说没有从同一端点返回不同类型的 API……如果您的目标是强类型语言,则不会。也许重新考虑你的信息。

标签: c# json json.net


【解决方案1】:

如果您不知道您将收到的 json,您可以使用

using System.Web.Script.Serialization;

命名空间。 (轻松搜索并添加此参考)

我使用以下代码将任何对象转换为有效的 json 对象。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;

namespace MinimalMonitoringClient.Helper
{
    public sealed class DynamicJsonConverter : JavaScriptConverter
    {
        public static object ConvertToObject(string data)
        {
            var serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
            return serializer.Deserialize(data, typeof(object));
        }

        private static string CleanJson(string data)
        {
            //Remove leading and ending whitespaces.
            data = data.Trim();

            //Java Script notation fixes
            if(data.StartsWith("["))
                data = data.Remove(0, 1);
            if(data.EndsWith("]"))
                data = data.Remove(data.Length - 1, 1);
            return data.Contains("={") ? data.Replace("={", ":{") : data;
        }

        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
        {
            private readonly IDictionary<string, object> _dictionary;

            public DynamicJsonObject(IDictionary<string, object> dictionary)
            {
                _dictionary = dictionary ?? throw new ArgumentNullException("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
    }
}

现在只需将任何 json 转换为对象

object jsonObject = DynamicJsonConverter.ConvertToObject(Json);

希望有帮助

【讨论】:

  • 我对 c# 很陌生,所以有很多我不明白的事情对不起,我正在寻找与我相同的问题,我找到了这个答案 stackoverflow.com/a/38680249/7872624 尽管在最后一步我仍然需要将对象转换为从 json 中提取的数据类型,我该怎么做?
  • (ClassToCastTo)objectToCast;或者只使用 JsonConvert.Deserialize(...);
【解决方案2】:

不确定我是否正确理解了您的问题,但您可以将对象反序列化为动态对象。例如:

var converter = new ExpandoObjectConverter(); dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json, converter);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    相关资源
    最近更新 更多