C# 如何使用 System.Text.Json 反序列化 Json 数据
C# How deserialize Json data using System.Text.Json
再次向好社区问好。这次我需要一些帮助来反序列化一些来自 Web API 的数据,使用 System.Text.Json。在到处搜索之后,我没有找到任何可以真正帮助我解决这个问题的东西
这是数据示例:
对于 UF 指标:
{
"UFs": [
{
"Valor": "30.008,40",
"Fecha": "2021-09-10"
}
]
}
对于美元指标:
{
"Dolares": [
{
"Valor": "791,28",
"Fecha": "2021-09-10"
}
]
}
对于 UTM 指标:
{
"UTMs": [
{
"Valor": "52.631",
"Fecha": "2021-09-01"
}
]
}
以及多组数据的美元样本:
{
"Dolares": [
{
"Valor": "767,10",
"Fecha": "2021-09-02"
},
{
"Valor": "768,36",
"Fecha": "2021-09-03"
},
{
"Valor": "766,53",
"Fecha": "2021-09-06"
},
{
"Valor": "770,33",
"Fecha": "2021-09-07"
},
{
"Valor": "777,94",
"Fecha": "2021-09-08"
},
{
"Valor": "787,51",
"Fecha": "2021-09-09"
},
{
"Valor": "791,28",
"Fecha": "2021-09-10"
}
]
}
这是 class 我需要反序列化为:
public class Indicador : IIndicador
{
public string Valor { get; set; }
public string Fecha { get; set; }
}
当我尝试使用此反序列化时,问题开始了:
var dataFromApi = await httpResponse.Content.ReadAsStringAsync();
var indicador = JsonSerializer.Deserialize<Indicador>(dataFromApi);
我也尝试过使用这个“解决方案”,但一点运气都没有:
var dataFromApi = await httpResponse.Content.ReadAsStringAsync();
var indicador = JsonSerializer.Deserialize<Dictionary<string,List<indicador>>>(dataFromApi);
到目前为止,唯一的解决方案是创建一个“容器”class,它可以帮助我处理那些奇怪的“UF”列表,因为这个 WebAPI 可以 return 除“UF”之外的多个其他经济指标可以更改为许多其他概念,有没有办法将来自 WebAPI 的内容映射到我的通用 Indicador class?,这个想法是当只有 1 个数据时使用简单对象,当有多个数据时使用 IEnumerable。我需要停止对每种可用指标的依赖。
提前致谢!
问题/改进领域
你的最后一段有点含糊,你没有更多的例子。因此,答案可能不像您正在寻找的那样具体。
multiple other economics indicators than "UFs"
如果能看到一些其他示例会很高兴。
map what ever comes from the WebAPI to my generic Indicador class
有可能,但其他数据的结构还有待观察。
最简单的例子
我认为你错过了反序列化过程的这一部分
List<Indicador> indicadors = dataDict["UFs"]; // <-- Will fail If "UFs" is not present
下面是顶级 C# 程序,用于将给定数据反序列化为 List<Indicador>
。
using System;
using System.Text.Json;
using System.Collections.Generic;
// test data
string dataFromApi = @"{
""UFs"": [
{
""Valor"": ""30.008,40"",
""Fecha"": ""2021-09-10""
},
{
""Valor"": ""40.008,50"",
""Fecha"": ""2021-10-10""
}
]
}";
var dataDict = JsonSerializer.Deserialize<Dictionary<string, List<Indicador>>>(dataFromApi);
List<Indicador> indicadors = dataDict["UFs"]; // <-- Will fail If "UFs" is not present
// print out the indicadors
indicadors.ForEach(indicador => Console.WriteLine(indicador));
// Using records because they are brief and come with a good default ToString() method
// You can use regular class if you require
public abstract record IIndicador(string Valor, string Fecha);
public record Indicador(string Valor, string Fecha): IIndicador(Valor, Fecha);
上面顶级C#程序的输出
Indicador { Valor = 30.008,40, Fecha = 2021-09-10 }
Indicador { Valor = 40.008,50, Fecha = 2021-10-10 }
如果不能保证“UFs”键,那么您可以使用一种字典方法来确定该键是否存在。例如
if (dataDict.ContainsKey("UFs")) ...
推测
在这里试图解决你最后一段的某些方面。 (您需要澄清这是否解决了您的所有顾虑并适应您的需求)System.Text.Json
也有 JsonConverterFactory
和 JsonConverter<T>
用于更高级的转换要求,如果您需要的话。
using System;
using System.Linq;
using System.Text.Json;
using System.Collections.Generic;
// test data
string multiDataFromApi = @"{
""UFs"": [
{
""Valor"": ""30.008,40"",
""Fecha"": ""2021-09-10""
},
{
""Valor"": ""40.008,50"",
""Fecha"": ""2021-10-10""
}
],
""UFOs"": [
{
""Valor"": ""30.008,40"",
""Fecha"": ""2021-09-10""
}
]
}";
string singleDataFromApi = @"{
""UFs"": [
{
""Valor"": ""30.008,40"",
""Fecha"": ""2021-09-10""
},
{
""Valor"": ""40.008,50"",
""Fecha"": ""2021-10-10""
}
]
}";
processDataFromApi(multiDataFromApi);
processDataFromApi(singleDataFromApi);
void processDataFromApi(string json)
{
var dataDict = JsonSerializer.Deserialize<Dictionary<string, List<Indicador>>>(json);
if (dataDict.Count == 1)
{
Console.WriteLine("-- Single Key Processing --");
List<Indicador> indicadors = dataDict.Values.First();
indicadors.ForEach(indicador => Console.WriteLine("\t{0}", indicador));
}
else
{
Console.WriteLine("-- Multi Key Processing --");
foreach (var keyValuePair in dataDict)
{
Console.WriteLine($"Processing Key: {keyValuePair.Key}");
List<Indicador> indicadors = keyValuePair.Value;
indicadors.ForEach(indicador => Console.WriteLine("\t{0}",indicador));
}
}
Console.WriteLine("-----------------------------");
}
// Using records because they are brief and come with a good default ToString() method
// You can use regular class if you require
public abstract record IIndicador(string Valor, string Fecha);
public record Indicador(string Valor, string Fecha): IIndicador(Valor, Fecha);
这将产生以下输出
-- Multi Key Processing --
Processing Key: UFs
Indicador { Valor = 30.008,40, Fecha = 2021-09-10 }
Indicador { Valor = 40.008,50, Fecha = 2021-10-10 }
Processing Key: UFOs
Indicador { Valor = 30.008,40, Fecha = 2021-09-10 }
-----------------------------
-- Single Key Processing --
Indicador { Valor = 30.008,40, Fecha = 2021-09-10 }
Indicador { Valor = 40.008,50, Fecha = 2021-10-10 }
-----------------------------
再次向好社区问好。这次我需要一些帮助来反序列化一些来自 Web API 的数据,使用 System.Text.Json。在到处搜索之后,我没有找到任何可以真正帮助我解决这个问题的东西
这是数据示例:
对于 UF 指标:
{
"UFs": [
{
"Valor": "30.008,40",
"Fecha": "2021-09-10"
}
]
}
对于美元指标:
{
"Dolares": [
{
"Valor": "791,28",
"Fecha": "2021-09-10"
}
]
}
对于 UTM 指标:
{
"UTMs": [
{
"Valor": "52.631",
"Fecha": "2021-09-01"
}
]
}
以及多组数据的美元样本:
{
"Dolares": [
{
"Valor": "767,10",
"Fecha": "2021-09-02"
},
{
"Valor": "768,36",
"Fecha": "2021-09-03"
},
{
"Valor": "766,53",
"Fecha": "2021-09-06"
},
{
"Valor": "770,33",
"Fecha": "2021-09-07"
},
{
"Valor": "777,94",
"Fecha": "2021-09-08"
},
{
"Valor": "787,51",
"Fecha": "2021-09-09"
},
{
"Valor": "791,28",
"Fecha": "2021-09-10"
}
]
}
这是 class 我需要反序列化为:
public class Indicador : IIndicador
{
public string Valor { get; set; }
public string Fecha { get; set; }
}
当我尝试使用此反序列化时,问题开始了:
var dataFromApi = await httpResponse.Content.ReadAsStringAsync();
var indicador = JsonSerializer.Deserialize<Indicador>(dataFromApi);
我也尝试过使用这个“解决方案”,但一点运气都没有:
var dataFromApi = await httpResponse.Content.ReadAsStringAsync();
var indicador = JsonSerializer.Deserialize<Dictionary<string,List<indicador>>>(dataFromApi);
到目前为止,唯一的解决方案是创建一个“容器”class,它可以帮助我处理那些奇怪的“UF”列表,因为这个 WebAPI 可以 return 除“UF”之外的多个其他经济指标可以更改为许多其他概念,有没有办法将来自 WebAPI 的内容映射到我的通用 Indicador class?,这个想法是当只有 1 个数据时使用简单对象,当有多个数据时使用 IEnumerable。我需要停止对每种可用指标的依赖。
提前致谢!
问题/改进领域
你的最后一段有点含糊,你没有更多的例子。因此,答案可能不像您正在寻找的那样具体。
multiple other economics indicators than "UFs"
如果能看到一些其他示例会很高兴。
map what ever comes from the WebAPI to my generic Indicador class
有可能,但其他数据的结构还有待观察。
最简单的例子
我认为你错过了反序列化过程的这一部分
List<Indicador> indicadors = dataDict["UFs"]; // <-- Will fail If "UFs" is not present
下面是顶级 C# 程序,用于将给定数据反序列化为 List<Indicador>
。
using System;
using System.Text.Json;
using System.Collections.Generic;
// test data
string dataFromApi = @"{
""UFs"": [
{
""Valor"": ""30.008,40"",
""Fecha"": ""2021-09-10""
},
{
""Valor"": ""40.008,50"",
""Fecha"": ""2021-10-10""
}
]
}";
var dataDict = JsonSerializer.Deserialize<Dictionary<string, List<Indicador>>>(dataFromApi);
List<Indicador> indicadors = dataDict["UFs"]; // <-- Will fail If "UFs" is not present
// print out the indicadors
indicadors.ForEach(indicador => Console.WriteLine(indicador));
// Using records because they are brief and come with a good default ToString() method
// You can use regular class if you require
public abstract record IIndicador(string Valor, string Fecha);
public record Indicador(string Valor, string Fecha): IIndicador(Valor, Fecha);
上面顶级C#程序的输出
Indicador { Valor = 30.008,40, Fecha = 2021-09-10 }
Indicador { Valor = 40.008,50, Fecha = 2021-10-10 }
如果不能保证“UFs”键,那么您可以使用一种字典方法来确定该键是否存在。例如
if (dataDict.ContainsKey("UFs")) ...
推测
在这里试图解决你最后一段的某些方面。 (您需要澄清这是否解决了您的所有顾虑并适应您的需求)System.Text.Json
也有 JsonConverterFactory
和 JsonConverter<T>
用于更高级的转换要求,如果您需要的话。
using System;
using System.Linq;
using System.Text.Json;
using System.Collections.Generic;
// test data
string multiDataFromApi = @"{
""UFs"": [
{
""Valor"": ""30.008,40"",
""Fecha"": ""2021-09-10""
},
{
""Valor"": ""40.008,50"",
""Fecha"": ""2021-10-10""
}
],
""UFOs"": [
{
""Valor"": ""30.008,40"",
""Fecha"": ""2021-09-10""
}
]
}";
string singleDataFromApi = @"{
""UFs"": [
{
""Valor"": ""30.008,40"",
""Fecha"": ""2021-09-10""
},
{
""Valor"": ""40.008,50"",
""Fecha"": ""2021-10-10""
}
]
}";
processDataFromApi(multiDataFromApi);
processDataFromApi(singleDataFromApi);
void processDataFromApi(string json)
{
var dataDict = JsonSerializer.Deserialize<Dictionary<string, List<Indicador>>>(json);
if (dataDict.Count == 1)
{
Console.WriteLine("-- Single Key Processing --");
List<Indicador> indicadors = dataDict.Values.First();
indicadors.ForEach(indicador => Console.WriteLine("\t{0}", indicador));
}
else
{
Console.WriteLine("-- Multi Key Processing --");
foreach (var keyValuePair in dataDict)
{
Console.WriteLine($"Processing Key: {keyValuePair.Key}");
List<Indicador> indicadors = keyValuePair.Value;
indicadors.ForEach(indicador => Console.WriteLine("\t{0}",indicador));
}
}
Console.WriteLine("-----------------------------");
}
// Using records because they are brief and come with a good default ToString() method
// You can use regular class if you require
public abstract record IIndicador(string Valor, string Fecha);
public record Indicador(string Valor, string Fecha): IIndicador(Valor, Fecha);
这将产生以下输出
-- Multi Key Processing --
Processing Key: UFs
Indicador { Valor = 30.008,40, Fecha = 2021-09-10 }
Indicador { Valor = 40.008,50, Fecha = 2021-10-10 }
Processing Key: UFOs
Indicador { Valor = 30.008,40, Fecha = 2021-09-10 }
-----------------------------
-- Single Key Processing --
Indicador { Valor = 30.008,40, Fecha = 2021-09-10 }
Indicador { Valor = 40.008,50, Fecha = 2021-10-10 }
-----------------------------