Я использую Pusher для реализации связи в реальном времени.
Вот функция, в которой я получаю данные от 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
});
}
Когда я отправляю событие из pusher, например это:
{
"foo": "bar"
}
Я не могу печатать из Unity. Вот логи:
my-event received
Newtonsoft.Json.Linq.JObject
{
"event": "my-event",
"data": "{\r\n \"foo\": \"bar\"\r\n}",
"channel": "my-channel"
}
Я пытаюсь поместить его в объект C# методом JObject.ToObject<>()
, но он не работает.
- Поскольку один из ключей JSON имеет имя
event
, это имя не может быть свойством объекта C# - Я знаю, что
event
и channel
будет string
типа, но какой будет тип data
?
Как бы вы преобразовали эту dynamic data
переменную в объект, зная, что это, по-видимому, JObject
?
РЕДАКТИРОВАТЬ
Я пытался сделать то, что предлагает @ derHu go, но он все еще не хочет печатать свойство 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;
}
Внутри метода, принимающего событие pusher (1 и 2 одновременно не пробовал):
PusherEvent pe = ((JObject)data).ToObject<PusherEvent>(); // 1
PusherEvent pe = JsonConvert.DeserializeObject<PusherEvent>(data); // 2
Debug.Log(pe.channel);
Вот мои логи: Как видите, это не регистрирует свойство канала и не генерирует никаких ошибок ...
EDIT 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();
}
}
}
РЕШЕНИЕ
Мне наконец удалось это сделать . Проблема заключалась в том, что объект root был 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();
}
}