使用来自 API 的 json 响应中的不规则节点/元素

Posted

技术标签:

【中文标题】使用来自 API 的 json 响应中的不规则节点/元素【英文标题】:Working with Irregular nodes/elements in json response from an API 【发布时间】:2021-11-07 05:38:31 【问题描述】:

我在处理来自 API 的 JSON 响应时遇到了一种情况。为了提供背景信息,我使用 REST API 使用 3.5 .net 框架从源中使用 API。 下面是 JSON 输出的一部分,我很难使用它。

一)

"value": 
  "Description": "Total  Calculated things",
  "2018": "5,820,456 ",
  "2019": "2,957,447 "

最后 2 个元素是动态的,它们往往会在 API 响应中发生变化。我期待下面提到的格式,但是在给定的时间点,源提供者无法更改它,因为 API 用于许多其他不同的程序。并且更改源 API 中的内容会使其他程序所有者发生更改。

b)

"value": 
    "Description": "Total  Calculated EQUITY AND LIABILITIES",
    "YearData": [ 
            "Data": "5,820,456",
            "Year": "2018"
        ,
        
            "Data": "2,957,447 ",
            "Year": "2019"
         ]

有什么办法可以克服这种情况>有什么办法可以将a转换为b

编辑 @Xerillio,谢谢。如何使用以下 JSON 格式实现相同的效果。

var json = @"
        
    ""entityData"": [
        
            ""name"": ""Statement of Comprehensive Income"",
            ""subattrOutput"": [
                
                    ""name"": ""Sales"",
                    ""subattrOutput"": [],
                    ""value"": 
                        ""Description"": ""Sales "",
                        ""2018"": ""8,704,888 "",
                        ""2019"": ""4,760,717 ""
                    ,
                    ""score"": ""99.5"",
                    ""valuetype"": ""object""
                ,
                
                    ""name"": ""Cost of goods sold"",
                    ""subattrOutput"": [],
                    ""value"": 
                        ""Description"": ""Cost of sales "",
                        ""2018"": ""(6,791,489) "",
                        ""2019"": ""(3,502,785) ""
                    ,
                    ""score"": ""99.75"",
                    ""valuetype"": ""object""
                
            ],
            ""value"": null,
            ""score"": ""98.63"",
            ""valuetype"": ""object""
        
    ]
";

【问题讨论】:

【参考方案1】:

我希望这更容易,但我只是在这里:


    class Program
    
        static async Task Main(string[] args)
        
            string json1 = @"""value"": ""Description"": ""Total  Calculated things"",""2018"": ""5,820,456 "",""2019"": ""2,957,447 """;
            string json2 = @"""value"": ""Description"": ""Total  Calculated EQUITY AND LIABILITIES"",""YearData"": [ ""Data"": ""5,820,456"",""Year"": ""2018"",""Data"": ""2,957,447 "",""Year"": ""2019"" ]";

            var obj1 = JsonConvert.DeserializeObject<ObjectResult>(json1);
            var obj2 = JsonConvert.DeserializeObject<ObjectResult>(json2);

            var res1 = CastObject<Result1>(obj1.Value.ToString());
            var res2 = CastObject<Result2>(obj2.Value.ToString());

            var invalidRes1 = CastObject<Result1>(obj2.Value.ToString());
            var invalidRes2 = CastObject<Result2>(obj1.Value.ToString());

            Console.WriteLine(res1);
            Console.WriteLine(res2);
        

        public static T CastObject<T>(string obj)
        
            return !TryCastObject(obj, out T result) ? default : result;
        


        public static bool TryCastObject<TOut>(string objToCast, out TOut obj)
        
            try
            
                obj = JsonConvert.DeserializeObject<TOut>(objToCast);
                return true;
            
            catch
            
                obj = default;
                return false;
            
        
    

    public class ObjectResult
    
        public object Value  get; set; 
    

    public class Result1
    
        [JsonProperty(PropertyName = "description")] public string Description  get; set; 
        [JsonProperty(PropertyName = "2018")] public string _2018  get; set; 
        [JsonProperty(PropertyName = "2019")] public string _2019  get; set; 
    

    public class Result2
    
        [JsonProperty(PropertyName = "Description")] public string Description  get; set; 
        [JsonProperty(PropertyName = "YearData")] public List<YearData> YearData  get; set; 
    

    public class YearData
    
        [JsonProperty(PropertyName = "Data")] public string Data  get; set; 
        [JsonProperty(PropertyName = "Year")] public string Year  get; set; 
    

真诚地做了大量的工作,因为 json 中有更多节点,我认为使用 JObject 是最好的选择,您将不得不在不止一个步骤中进行去现实化:(

【讨论】:

【参考方案2】:

根据 JSON 结构的大小,您可以将其反序列化为 Dictionary 并手动将其映射为正确的格式:

var json = @"

    ""value"": 
        ""Description"": ""Total  Calculated things"",
        ""2018"": ""5,820,456 "",
        ""2019"": ""2,957,447 ""
    
";

var badObj = JsonSerializer.Deserialize<BadFormat>(json);
var result = new WrapperType

    Value = new ProperlyFormattedType()
;

foreach (var pair in badObj.Value)

    if (pair.Key == "Description")
    
        result.Value.Description = pair.Value;
    
    else if (int.TryParse(pair.Key, out int _))
    
        result.Value.YearData
            .Add(new DatedValues
            
                Year = pair.Key,
                Data = pair.Value
            );
    


// Data models...

public class BadFormat

    [JsonPropertyName("value")]
    public Dictionary<string, string> Value  get; set; 



public class WrapperType

    public ProperlyFormattedType Value  get; set; 


public class ProperlyFormattedType

    public string Description  get; set; 
    public List<DatedValues> YearData  get; set;  = new List<DatedValues>();


public class DatedValues

    public string Year  get; set; 
    public string Data  get; set; 

查看example fiddle here。

【讨论】:

以上是关于使用来自 API 的 json 响应中的不规则节点/元素的主要内容,如果未能解决你的问题,请参考以下文章

以(Json 格式)解析来自 Google Place api 响应的数据

如何通过匹配来自两个 API 的 id 来查看来自两个 JSON API 的响应到单个回收器视图适配器中?

检查来自 API 的响应是不是为有效 JSON

如何在 Swift 中解析来自 Alamofire API 的 JSON 响应?

将来自 API 的响应作为来自我的节点服务器的响应传递抛出

将json响应添加到flutter中的列表