1

I am trying to deserialize a JSON file with a complex structure in C#, but I'm facing difficulties due to multi-format content within arrays. Unfortunately, I cannot change the JSON format. Here's an example of the JSON file:

{
    "messages": [
        {
            "date": "2023-05-19T17:58:17.329Z",
            "message": {
                "alert": {
                    "type": "info",
                    "message": [
                        {
                            "name": "AshesAppTest1",
                            "argType": "nonAvatarPlayer"
                        },
                        " has connected to the game server"
                    ]
                }
            },
            "activePlayer": null
        },
        {
            "date": "2023-05-19T18:56:32.304Z",
            "message": [
                {
                    "name": "AshesAppTest2",
                    "argType": "player"
                },
                " ",
                "Hello world!"
            ]
        }
    ]
}

To handle this complex JSON structure, I've created the following C# class structure and a custom converter:

public class GamePlayMessage
{
    public string date { get; set; }
    public GamePlayPlayer activePlayer { get; set; }

    [JsonProperty("message")]
    [JsonConverter(typeof(GamePlayMessageDataConverter))]
    public GamePlayMessageData MessageData { get; set; }
}

public class GamePlayMessageData
{
    [JsonProperty("alert")]
    public GamePlayComplexMessage ComplexMessage { get; set; }
}

public class GamePlayComplexMessage
{
    public string type;
    public List<object> message;
}

class GamePlayMessageDataConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(GamePlayMessageData));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Object)
        {
            return token.ToObject<GamePlayMessageData>();
        }
        else if (token.Type == JTokenType.Array)
        {
            Debug.Log(token);
            return new GamePlayMessageData
            {
                ComplexMessage = new GamePlayComplexMessage
                {
                    type = "noType",
                    message = new List<object>(token.ToArray<object>())
                }
            };
        }
        return null;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

The above code works fine until the line message = new List(token.ToArray()), where I need to utilize another converter. I'm not sure how to run a converter within another converter. Could you please assist me in achieving this? Thank you in advance for your help.

  • What do you need another converter for? Converter it is just a function , so just create a function or add some code instead – Serge May 21 '23 at 00:53

1 Answers1

1

I would create code like this

var data = JsonConvert.DeserializeObject<Data>(json);

class GamePlayMessageDataConverter : JsonConverter<GamePlayMessageData>
{
    public override GamePlayMessageData ReadJson(JsonReader reader, Type objectType, GamePlayMessageData existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);

        GamePlayMessageData data = null;

        if (token.Type == JTokenType.Object)
        {
            data = token.ToObject<GamePlayMessageData>();
        }
        else if (token.Type == JTokenType.Array)
        {
            data = new GamePlayMessageData
            {
                ComplexMessage = new GamePlayComplexMessage
                {
                    type = "noType",
                    message = token.ToObject<List<object>>()
                }
            };
        }

        if (data != null)
            for (int i = 0; i < data.ComplexMessage.message.Count; i++)
            {
                if (data.ComplexMessage.message[i].GetType().ToString() == 
                                              "Newtonsoft.Json.Linq.JObject")
                    data.ComplexMessage.message[i] = 
                      ((JObject)data.ComplexMessage.message[i]).ToObject<Arg>();
            }

        return data;
    }

    public override void WriteJson(JsonWriter writer, GamePlayMessageData value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

test

Console.WriteLine(data.Messages[0].MessageData.ComplexMessage.message[0]
                   .GetType().ToString()); // "Arg"

classes

public partial class Data
{
    [JsonProperty("messages")]
    public List<GamePlayMessage> Messages { get; set; }
}

public class GamePlayMessage
{
    public string date { get; set; }
    public GamePlayPlayer activePlayer { get; set; }

    [JsonProperty("message")]
    [JsonConverter(typeof(GamePlayMessageDataConverter))]
    public GamePlayMessageData MessageData { get; set; }
}

public class GamePlayMessageData
{
    [JsonProperty("alert")]
    public GamePlayComplexMessage ComplexMessage { get; set; }
}

public class GamePlayComplexMessage
{
    public string type;
    public List<object> message;
}

public partial class Arg
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("argType")]
    public string ArgType { get; set; }
}
Serge
  • 40,935
  • 4
  • 18
  • 45