如何在C#中运行一个转换器以处理复杂JSON文件中的多格式内容?

huangapple go评论72阅读模式
英文:

How do I run a converter within another converter to handle multi-format content in a complex JSON file in C#?

问题

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.

英文:

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:

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

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(&quot;message&quot;)]
    [JsonConverter(typeof(GamePlayMessageDataConverter))]
    public GamePlayMessageData MessageData { get; set; }
}

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

public class GamePlayComplexMessage
{
    public string type;
    public List&lt;object&gt; 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&lt;GamePlayMessageData&gt;();
        }
        else if (token.Type == JTokenType.Array)
        {
            Debug.Log(token);
            return new GamePlayMessageData
            {
                ComplexMessage = new GamePlayComplexMessage
                {
                    type = &quot;noType&quot;,
                    message = new List&lt;object&gt;(token.ToArray&lt;object&gt;())
                }
            };
        }
        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<object>(token.ToArray<object>()), 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.

答案1

得分: 1

Here is the code you provided translated into Chinese:

我会创建类似这样的代码

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

class GamePlayMessageDataConverter : JsonConverter
{
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<参数>();
		}

	return data;
}

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

}

测试

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

public partial class 数据
{
[JsonProperty("messages")]
public List 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 message;
}

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

[JsonProperty("argType")]
public string ArgType { get; set; }

}


Please note that I have translated the code as requested, including class and property names.

<details>
<summary>英文:</summary>

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&lt;GamePlayMessageData&gt;();
	}
	else if (token.Type == JTokenType.Array)
	{
		data = new GamePlayMessageData
		{
			ComplexMessage = new GamePlayComplexMessage
			{
				type = &quot;noType&quot;,
				message = token.ToObject&lt;List&lt;object&gt;&gt;()
			}
		};
	}

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

	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(&quot;message&quot;)]
[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(&quot;argType&quot;)]
public string ArgType { get; set; }

}

huangapple
  • 本文由 发表于 2023年5月21日 08:13:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76297817.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定

  • 开发者交流平台

    本页二维码