gpt4 book ai didi

c# - 当某些JSON对象为字符串而某些为数组时,如何将JSON转换为列表字符串?

转载 作者:行者123 更新时间:2023-11-30 14:57:50 31 4
gpt4 key购买 nike

我的JSON看起来像

{
"d": {
"__type": "CubeJsonData",
"SessionID": null,
"Code": 0,
"Message": "",
"Rows": {},
"Columns": {
"Place 1": [
0,
1
],
"Place 2": [
0,
2,
4,
6
],
},
"Set": [
[
"Number 1"
],
[
"Number 2"
],
[
"Number 3"
]
]
}
}


我需要获得以下值

List<string> Columns must contain: "Place 1", "Place 2"
List<string> Set must contain: "Number 1", "Number 2", "Number 3"


我的电话是

var settings = new JsonSerializerSettings();
settings.Converters.Add(new AssosiativeArrayConverter());
var staffAlerts = JsonConvert.DeserializeObject<List<AlertDetails>>(jo.ToString(), settings);


我的JsonConverter是

class AssosiativeArrayConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(string)) || (objectType == typeof(List<string>));
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
var l = new List<string>();
reader.Read();
while (reader.TokenType != JsonToken.EndArray)
{
l.Add(reader.Value as string);

reader.Read();
}
return l;
}
else
{
return new List<string> { reader.Value as string };
}
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{//to do
}
}


我的课是

class StaffDetail
{
public string __type { get; set; }
public string SessionID { get; set; }
public string Code { get; set; }
public string Message { get; set; }

[JsonConverter(typeof(AssosiativeArrayConverter))]
public List<string> Rows { get; set; }
[JsonConverter(typeof(AssosiativeArrayConverter))]
public List<string> Columns { get; set; }
[JsonConverter(typeof(AssosiativeArrayConverter))]
public List<string> Set { get; set; }
}


我收到一个错误


  无法将当前JSON对象(例如{“ name”:“ value”})反序列化为类型'System.Collections.Generic.List`1 [ReportingServicesAlerts.AlertDetails]',因为该类型需要JSON数组(例如[1,2, 3])正确反序列化。
  要解决此错误,可以将JSON更改为JSON数组(例如[1,2,3]),也可以更改反序列化类型,使其成为普通的.NET类型(例如,不像整数这样的原始类型,也不像这样的集合类型。可以从JSON对象反序列化的数组或列表)。还可以将JsonObjectAttribute添加到类型中,以强制其从JSON对象反序列化。


您能帮我弄清楚我做错了什么吗?

最佳答案

您在这里遇到很多问题。让我从出现此错误的原因开始:您的JSON包含一个外部对象,但是您尝试将其反序列化为列表。这行不通。如果JSON中只有一个对象,则需要反序列化为一个对象。

第二个问题,StaffDetail类的数据不在JSON的顶层;它比外部JSON对象的d属性的值低一级。要解决此问题,您需要引入包装器类并将其反序列化。然后,您可以从包装器中检索StaffDetail

第三个问题,似乎您正在尝试将JSON中的ColumnsSet数据展平为类中的List<string>属性。看来您已经正确认识到需要转换器才能执行此操作;但是,您的转换器无法正确处理JSON数据-假设它将仅获取简单的字符串数组或简单的字符串。在JSON中,ColumnsSet都不以这种方式构造,而且,两者的数据构造都不同。前者是一个对象,其中包含其属性为整数数组的属性。后者是字符串数组的数组。由于它们是不同的结构,因此需要对它们进行不同的处理。我建议在这种情况下使用两个不同的转换器。

第四,当您使用StaffDetail属性正确装饰[JsonConverter]类以指示哪些属性应使用转换器时,您还错误地将转换器添加到了序列化程序设置中。问题是您的转换器在CanConvert中说它可以处理任何字符串或任何字符串列表。如果您在设置中应用转换器,则意味着Json.Net将尝试将转换器用于字符串或字符串列表中任何位置的任何属性。显然,您不希望这样做-您的转换器实际上只是为了处理一种特定情况。

第五,看起来您还用Rows属性修饰了[JsonConverter]属性,但是JSON显示了一个空对象。该字段中是否有您关心的任何数据?如果不是,只需将其声明为object即可;如果您确实需要,请举例说明其中可能存在的情况。或者,如果您知道它的结构与ColumnsSet相同,则可以将其保留为List<string>并重用这些转换器之一。

您的问题中还有其他一些小问题,例如由于多余的逗号(已由@frno指出)而使JSON无效,并且您对JsonConvert.DeserializeObject()的调用提到了一个名为AlertDetails的类,但该类您显示的名称实际上是StaffDetail。但是,我们将这些归结为简单的复制粘贴错误。

ew!

好,那么我们如何解决所有这些问题?

让我们从您的课程开始。我提到您需要一个包装器类,因为您的数据实际上是JSON中的下一层。如下所示:

class Wrapper
{
public StaffDetail d { get; set; }
}


对于您的 StaffDetail类,我已经更改了 ColumnsSet属性以使用不同的转换器,因为每个JSON都不同。接下来,我将定义这些转换器。我也将 Rows的类型更改为 object并暂时删除了 [JsonConverter]属性,因为尚不清楚该字段的处理方式。如果数据的结构类似于 ColumnsSet,则可以将其改回并使用适当的转换器,如我所提到的。

class StaffDetail
{
public string __type { get; set; }
public string SessionID { get; set; }
public string Code { get; set; }
public string Message { get; set; }
public object Rows { get; set; }

[JsonConverter(typeof(ColumnsConverter))]
public List<string> Columns { get; set; }

[JsonConverter(typeof(SetConverter))]
public List<string> Set { get; set; }
}


这是将处理 Columns数据的转换器。该转换器将使用JSON对象,并将属性名称提取到字符串列表中。

class ColumnsConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// this converter can handle converting some JSON to a List<string>
return objectType == typeof(List<string>);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Convert an object to a flat list of strings containing
// just the property names from the object.
JObject obj = JObject.Load(reader);
return obj.Properties().Select(p => p.Name).ToList();
}

public override bool CanWrite
{
get { return false; }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}


这是将处理 Set数据的转换器。该转换器将采用字符串数组的数组,并将其转换为平面字符串列表。

class SetConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// this converter can handle converting some JSON to a List<string>
return objectType == typeof(List<string>);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Convert an array of arrays of strings to a flat list of strings
JArray array = JArray.Load(reader);
return array.Children<JArray>()
.SelectMany(ja => ja.Children(), (ja, jt) => jt.Value<string>()).ToList();
}

public override bool CanWrite
{
get { return false; }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}


要反序列化,您可以像这样调用 JsonConvert.DeserializeObject()。注意我如何反序列化到 Wrapper类,然后从中检索 StaffDetail。还要注意,我不需要(在这种情况下也不应该)将转换器传递给解串器。通过 [JsonConverter]类属性上的 StaffDetail属性,它们将在适当的时间自动获取。

StaffDetail detail = JsonConvert.DeserializeObject<Wrapper>(json).d;


这是一个简单的演示程序,展示了它们如何工作:

class Program
{
static void Main(string[] args)
{
string json = @"
{
""d"": {
""__type"": ""CubeJsonData"",
""SessionID"": null,
""Code"": 0,
""Message"": """",
""Rows"": {},
""Columns"": {
""Place 1"": [
0,
1
],
""Place 2"": [
0,
2,
4,
6
]
},
""Set"": [
[
""Number 1""
],
[
""Number 2""
],
[
""Number 3""
]
]
}
}";

StaffDetail detail = JsonConvert.DeserializeObject<Wrapper>(json).d;

Console.WriteLine("Columns: " + string.Join(", ", detail.Columns));
Console.WriteLine("Set: " + string.Join(", ", detail.Set));
}
}


输出:

Columns: Place 1, Place 2
Set: Number 1, Number 2, Number 3

关于c# - 当某些JSON对象为字符串而某些为数组时,如何将JSON转换为列表字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20134266/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com