【发布时间】:2020-06-18 23:18:50
【问题描述】:
我正在使用 Pusher 来实现实时通信。
这是我从推送器获取数据的函数:
private void PusherOnConnected(object sender)
{
Debug.Log("Connected");
channel.Bind("my-event", (dynamic data) =>
{
Debug.Log("my-event received");
Debug.Log(data.GetType().ToString());
Debug.Log(((JObject)data).ToString()); // <-- last line logged
// See EDIT to see what lines have been added
});
}
当我像这样从推送器发送事件时:
{
"foo": "bar"
}
我无法从 Unity 打印。以下是日志:
my-event received
Newtonsoft.Json.Linq.JObject
{
"event": "my-event",
"data": "{\r\n \"foo\": \"bar\"\r\n}",
"channel": "my-channel"
}
我正在尝试使用 JObject.ToObject<>() 方法将其放入 C# 对象中,但它不起作用。
- 由于 JSON 的键之一具有名称
event,因此该名称不能是 C# 对象的属性 - 我知道
event和channel是string类型,但data的类型是什么?
如果知道显然是JObject,您将如何将此dynamic data 变量转换为对象?
编辑
我尝试按照@derHugo 的建议进行操作,但它仍然不想打印 C# 属性:
PusherEvent.cs
using Newtonsoft.Json;
using System;
[Serializable]
public class PusherEvent
{
[JsonProperty("event")]
public string theEvent;
public string channel;
public Data data;
}
[Serializable]
public class Data
{
public string foo;
}
在接收推送事件的方法内部(我没有同时尝试1和2):
PusherEvent pe = ((JObject)data).ToObject<PusherEvent>(); // 1
PusherEvent pe = JsonConvert.DeserializeObject<PusherEvent>(data); // 2
Debug.Log(pe.channel);
这是我的日志: 如您所见,它不会记录通道属性,也不会抛出任何错误...
编辑 2:完整代码
PusherManager.cs
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PusherClient;
using UnityEngine;
public class PusherManager : MonoBehaviour
{
public static PusherManager instance = null;
private Pusher pusher;
private Channel channel;
async Task Start()
{
if (instance == null)
{
instance = this;
}
else if (instance != this)
{
Destroy(gameObject);
}
DontDestroyOnLoad(gameObject);
await InitialisePusher();
}
private async Task InitialisePusher()
{
if (pusher == null)
{
pusher = new Pusher("<my-secret-key>", new PusherOptions()
{
Cluster = "eu",
Encrypted = true
});
pusher.Error += OnPusherOnError;
pusher.ConnectionStateChanged += PusherOnConnectionStateChanged;
pusher.Connected += PusherOnConnected;
channel = await pusher.SubscribeAsync("my-channel");
channel.Subscribed += OnChannelOnSubscribed;
await pusher.ConnectAsync();
}
}
private void PusherOnConnected(object sender)
{
Debug.Log("Connected");
channel.Bind("my-event", (dynamic data) =>
{
Debug.Log("my-event received");
Debug.Log(data.GetType().ToString());
Debug.Log(((JObject)data).ToString());
PusherEvent pe = ((JObject)data).ToObject<PusherEvent>();
// PusherEvent pe = JsonConvert.DeserializeObject<PusherEvent>(((JObject)data).ToString());
Debug.Log(pe.channel);
});
}
private void PusherOnConnectionStateChanged(object sender, ConnectionState state)
{
Debug.Log("Connection state changed");
}
private void OnPusherOnError(object s, PusherException e)
{
Debug.Log("Errored");
}
private void OnChannelOnSubscribed(object s)
{
Debug.Log("Subscribed");
}
async Task OnApplicationQuit()
{
if (pusher != null)
{
await pusher.DisconnectAsync();
}
}
}
解决方案
我终于成功了。问题实际上是根对象是JObject,而该对象的data 属性是string,~~ 而不是另一个JObject ~~:
// PusherManager.cs
// ...
PEvent<FireworkInfo> pe = new PEvent<FireworkInfo>(pusherEvent);
Debug.Log(pe);
// ...
// PEvent.cs
using Newtonsoft.Json.Linq;
using System;
[Serializable]
public class PEvent<T>
{
public string @event;
public string channel;
public T data;
public PEvent(dynamic pusherEvent)
{
this.@event = pusherEvent["event"];
this.channel = pusherEvent["channel"];
this.data = JObject.Parse((string)pusherEvent["data"]).ToObject<T>();
}
public override string ToString()
{
return data.ToString();
}
}
【问题讨论】:
-
你能发布你的完整代码吗?
-
完成:完整代码@derHugo
-
这个
Bind回调是否有可能在不同的线程上执行.. 可能有 ab 异常但您在控制台中看不到?您可以尝试将其包装在try { PusherEvent pe = ((JObject)data).ToObject<PusherEvent>(); Debug.Log(pe.channel); } catch(Exception e) { Debug.LogError($"{e.GetType} - {e.Message}/n{e.stackTrace}"); } -
@derHugo 非常感谢,正在取得进展:
Newtonsoft.Json.JsonSerializationException - Error converting value "{ "foo": "bar" }" to type 'Data'. Path 'data'.
标签: c# visual-studio unity3d pusher