【问题标题】:Converting unknown JSON string to correct object将未知的 JSON 字符串转换为正确的对象
【发布时间】:2018-06-23 11:18:01
【问题描述】:

我从套接字连接接收到未知字符串。它始终遵循格式

{
    “eventType”: “playerListUpdate”
    “data”: “...changes...”
}

我正在反序列化它使用:

var message = JsonConvert.DeserializeObject<NetworkMessage>(data);

NetworkMessage 看起来像这样:

public class NetworkMessage
{
    public string data;
    public string eventType;
}

我的问题是,有时数据属性保留为字符串,而有时它包含具有更复杂数据的数组(想想 DB 结果)。因此,当我尝试用数据中的数组反序列化字符串时,它会失败。

更复杂数据的一个例子是

{"eventType":"latestPlayersList","data":[{"id":1,"firstName":"Harry"},{"id":2,"firstName":"Ted"},{"id":3,"firstName":"Michael"},{"id":4,"firstName":"Mike"}],"from":"server"}

如何根据 eventType 的值将 JSON 字符串反序列化为不同的 VO?

【问题讨论】:

  • 请展示一个复杂数据的例子。
  • 抱歉,添加进去了。
  • 你用反射检查类型了吗?
  • data的类型,基于eventType中的值?

标签: c# json unity3d


【解决方案1】:

反序列化的一种方法是直接转到JObject

var jObject = JsonConvert.DeserializeObject<JObject>(json);

现在您可以像这样访问属性值:

var eventType = jObject.Value<string>("eventType")

现在您还可以扩展它来检查eventType 的值,然后反序列化为正确的对象类型。所以我们可以有一个这样的泛型类:

public class NetworkMessage<T>
{
    public string EventType;
    public T Data;
}

public class Player
{
    public int Id { get; set; }
    public string FirstName { get; set; }
}

并根据eventType的值来决定我们使用什么泛型类型。请注意,这不是世界上最高效的代码,因为它会反序列化两次,但它会起作用:

private void ProcessJson(string json)
{
    var jObject = JsonConvert.DeserializeObject<JObject>(json);

    switch (jObject.Value<string>("eventType"))
    {
        case "playerListUpdate":
            HandlePlayerListUpdate(jObject.ToObject<NetworkMessage<string>>());
            break;
        case "latestPlayersList":
            HandleLatestPlayersList(jObject.ToObject<NetworkMessage<List<Player>>>());
            break;
    }
}

private void HandlePlayerListUpdate(NetworkMessage<string> playerListUpdateMessage)
{
    Console.WriteLine($"Player list update: {playerListUpdateMessage.Data}");
}

private void HandleLatestPlayersList(NetworkMessage<List<Player>> latestPlayersListMessage)
{
    Console.WriteLine($"Latest Players list: {latestPlayersListMessage.Data.Count} players");
}

【讨论】:

    【解决方案2】:

    您可以使用 Newtonsoft.json。试试下面。

    var files = JObject.Parse(YourJSONHere);
    var recList = files.SelectTokens("$..eventType").ToList();
    for (int i = 0; i < recList.Count(); i++)
            {
                if (recList[i].ToString().Contains("latestPlayersList"))
                {
                    var data = files.SelectTokens("$..data").ToList();
                    Console.Write(data.FirstOrDefault());
                }
    
                if (recList[i].ToString().Contains("playerListUpdate"))
                {
                    var data = files.SelectTokens("$..data").ToList();
                }
    
            }
    

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 2022-01-06
      • 1970-01-01
      • 2017-09-04
      • 1970-01-01
      • 2016-09-18
      • 2019-08-27
      • 2020-05-27
      • 1970-01-01
      相关资源
      最近更新 更多