Harry Northover
Harry Northover

Reputation: 572

Converting unknown JSON string to correct object

I’m receiving an unknown string from a socket connection. It always follows the format

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

I’m deserialising it using:

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

With the NetworkMessage looking like this:

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

My problem is that sometimes the data property stays as a string, and other times it contains an array with more complex data (think DB results). So when I try to deserialise a string with an array in data, it fails.

An example of more complex data is

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

How can I deserialise a JSON string into different VO depending on the value of eventType?

Upvotes: 2

Views: 1936

Answers (2)

Prany
Prany

Reputation: 2143

You can use Newtonsoft.json. Try below.

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();
            }

        }

Upvotes: 0

DavidG
DavidG

Reputation: 119186

One way to deserialise is to go directly to a JObject

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

Now you can access property values like this:

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

Now you could also extend this to check the value of eventType and then deserialise to the right object type. So we could have a generic class like this:

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

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

And decide what the generic type we use based on the value of eventType. Note, this isn't the most efficient code in the world as it deserialises twice, but it will work:

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");
}

Upvotes: 2

Related Questions