是否可以使用 C# 派生类反序列化来自不同 Web 源的 JSON?

Is it possible to deserialize JSON from different web sources with C# derived classes?

提问人:António Pragana 提问时间:6/2/2023 最后编辑:António Pragana 更新时间:6/6/2023 访问量:34

问:

意向:从不同的 Web 源接收 json 格式的数据,返回不同的数据列表,并对其进行反序列化。

几乎可以肯定这是一个新手 C# 问题:( 没有派生类的经验...... 也许我正在尝试一个不可能的数据操作......

1 - 创建了一个带有抽象索引的抽象数据类(通过命名字符串访问数据)。然后创建 2 个派生类,其中包含每个源的字段。到目前为止没有问题。

    public abstract class Data
    {
        public abstract object this[string index] { get; set; }
    }
    public class Type1 : Data
    {
        public DateTime DATA_COTA { get; set; }
        public string MOEDABASE { get; set; }
        public override object this[string index]
        {
            get
            {
                switch (index.Substring(1))
                {
                    case "DATA_COTA":
                        return DATA_COTA;

                    case "MOEDABASE":
                        return MOEDABASE;

                    default:
                        throw new InvalidOperationException($"campo {index} inválido");
                }
            }
            set
            {
                ;
            }
        }
    }
    public class Type2 : Data
    {
        public string MOEDA { get; set; }
        public decimal VALFIX { get; set; }
        public override object this[string index]
        {
            get
            {
                switch (index.Substring(1))
                {
                    case "MOEDA":
                        return MOEDA;

                    case "VALFIX":
                        return VALFIX;

                    default:
                        throw new InvalidOperationException($"campo {index} inválido");
                }
            }
            set
            {
                ;
            }
        }
    }

2 - 创建一个抽象根类,其中包含一个公共字符串字段 (odatacontext) 和从每个站点返回的字段列表。由于我没有在每个类定义中提及每种类型,因此我认为它永远不会起作用。我尝试了很多变化/技巧,但这是唯一一个可以编译但不起作用的版本:(

    public abstract class Root
    {
        [JsonProperty("@odata.context")]
        public string odatacontext { get; set; }
        public abstract List<Data> value { get; set; }
    }
    public class RootType1 : Root
    {
        public override List<Data> value
        {
            get
            {
                return this.value;
            }
            set
            {
                //List<Type1> value = value.Select(s => (Type1)s).ToList();
                this.value = value;
            }
        }
    }
    public class RootType2 : Root
    {
        public override List<Data> value
        {
            get
            {
                return this.value;
            }
            set
            {
                //List<Type2> value = value.Select(s => (Type2)s).ToList();
                this.value = value;
            }
        }
    }

3 - 最后是代码......引用 obj.value 时出现堆栈溢出

                           using (HttpClient httpClient = new HttpClient())
                            {
                                HttpResponseMessage httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;

                                string json = httpResponseMessage.Content.ReadAsStringAsync().Result;
                                if (!httpResponseMessage.IsSuccessStatusCode)
                                    throw new InvalidOperationException(json);

                                Root obj;
                                switch (name)
                                {
                                    case "Type1":
                                        obj = JsonConvert.DeserializeObject<RootType1>(json);
                                        break;

                                    case "Type2":
                                        obj = JsonConvert.DeserializeObject<RootType2>(json);
                                        break;

                                    default:
                                        throw new InvalidOperationException($"{name} não previsto");
                                }

                                foreach (var item in **obj.value**)
                                {
                                    foreach (SqlParameter param in cmdUPD.Parameters)
                                    {
                                        string paramName = param.ParameterName;
                                        if (name != "@RETURN_VALUE")
                                            cmdUPD.Parameters[paramName].Value = item[paramName];
                                    }

                                    cmdUPD.ExecuteNonQuery();
                                }
                            }

正如我被要求提供 json 一样......然后我必须发送“真实的东西”...... 我正在发送实际的解决方案(1 和 2 ...工作,但使用重复的代码)......然后 JSON 流......然后是预期的解决方案(4 和 5)。我没有显示派生类(或任何其他解决方案),因为我不知道如何:( 目的是让所有(我有几个)类 Root* 派生自一个 Root 类,以及一段模糊的代码,只改变 json 反序列化。

1 - ACTUAL 类定义

   public abstract class Data
    {
        public abstract object this[string index] { get; set; }
    }
    public class Câmbios : Data
    {
        public int SGC_ID { get; set; }
        public DateTime DtCâmbio { get; set; }
        public string MdaBase { get; set; }
        public string Mda { get; set; }
        public decimal Fixing { get; set; }
        public override object this[string index]
        {
            get
            {
                switch (index.Substring(1))
                {
                    case "DtCâmbio":
                        return DtCâmbio;

                    case "MdaBase":
                        return MdaBase;

                    case "Mda":
                        return Mda;

                    case "Fixing":
                        return Fixing;

                    default:
                        throw new InvalidOperationException($"campo {index} inválido");
                }
            }
            set
            {
                ;
            }
        }
    }
    public class RootCâmbios
    {
        [JsonProperty("@odata.context")]
        public string odatacontext { get; set; }
        public List<Câmbios> value { get; set; }
    }
   public class Índice : Data
    {
        public int SGC_ID { get; set; }
        public string Indexante { get; set; }
        public DateTime Data { get; set; }
        public decimal Valor { get; set; }
        public string OmitirLista { get; set; }
        public override object this[string index]
        {
            get
            {
                switch (index.Substring(1))
                {
                    case "Indexante":
                        return Indexante;

                    case "Data":
                        return Data;

                    case "Valor":
                        return Valor;

                    case "OmitirLista":
                        return OmitirLista;

                    default:
                        throw new InvalidOperationException($"campo {index} inválido");
                }
            }
            set
            {
                ;
            }
        }
    }
    public class RootÍndices
    {
        [JsonProperty("@odata.context")]
        public string odatacontext { get; set; }
        public List<Índice> value { get; set; }
    }

2 - 实际程序(复制:()

        switch (name)
        {
            case "Câmbios":
                //RESOLVER ... analisar se há forma de consumir o registo no caso  do odatacontext ser null ... ler Root ???
                //Root obj = JsonConvert.DeserializeObject<RootCâmbios>(json);
                RootCâmbios objCâmbios = JsonConvert.DeserializeObject<RootCâmbios>(json);
                if (!objCâmbios.odatacontext.StartsWith($"{urlBase}/$metadata#{SGC_name}"))
                    throw new InvalidOperationException("falha na validação do contexto");

                foreach (Data item in objCâmbios.value)
                {
                    foreach (SqlParameter param in cmdINS.Parameters)
                    {
                        string paramName = param.ParameterName;
                        if (!(param.ParameterName == "@RETURN_VALUE" || param.ParameterName == "@EXEC_Dia"))
                            cmdINS.Parameters[paramName].Value = item[paramName];
                    }

                    cmdINS.ExecuteNonQuery();
                }
                break;

            case "Índices":
                RootÍndices objÍndices = JsonConvert.DeserializeObject<RootÍndices>(json);
                if (objÍndices.odatacontext != null)
                {
                    if (!objÍndices.odatacontext.StartsWith($"{urlBase}/$metadata#{SGC_name}"))
                        throw new InvalidOperationException("falha na validação do contexto");

                    foreach (Data item in objÍndices.value)
                    {
                        foreach (SqlParameter param in cmdINS.Parameters)
                        {
                            string paramName = param.ParameterName;
                            if (!(param.ParameterName == "@RETURN_VALUE" || param.ParameterName == "@EXEC_Dia"))
                                cmdINS.Parameters[paramName].Value = item[paramName];
                        }

                        cmdINS.ExecuteNonQuery();
                    }
                }
                break;

            default:
                throw new InvalidOperationException($"{name} não previsto");
        }

3 - JSON 数据

Câmbios {“@odata.context”:“http://gasgc.montepio.com/odatacustom/maintenancedata/$metadata#fixingrates#9ee42a020a03ff123ae687ecfc1ce91ee9e2768e0a1274c518516e62c66fcc175b8adda21cf69cd59a70afcc8a08c334cda15b00f1c78239c8e1430f5f363da3”,“value”:[{“fixingrates_ID”:1,“DtC\u00e2mbio”:“2023-05-26T00:00:00+01:00”,“MdaBase”:“USD”,“Mda”:“EUR”,“Fixing”:1.075100000000000},{“fixingrates_ID”:2,“DtC\u00e2mbio”:“2023-05-26T00:00:00+01:00”,“MdaBase”:“GBP“,”Mda“:”EUR“,”Fixing“:0.868130000000000},{”fixingrates_ID“:3,”DtC\u00e2mbio“:”2023-05-26T00:00:00+01:00“,”MdaBase“:”JPY“,”Mda“:”EUR“,”Fixing“:2023-05-26T00:00:00:00:00:JPY”,“Mda”:“EUR”,“Fixing”::::2023-05-26T00:00:00+01:00“,”MdaBase“:”JPY“,”Mda“:”EUR“,”Fixing“:2023-05-26T00-26T00:00:00:00:00”,“MdaBase”:“JPY”,“Mda”:“EUR”,“Fixing”:::2023-05-26T00-00:00:00:00“,”MdaBase“:”JPY“,”Mda“:”EUR“,”Fixing“:2023-05-05-26T00:00:00:00:00”,“MdaBase”:“JPY”,“Mda”:“EUR”,“Fixing”:2023-05-26T00:00:00:00:00+01:00“,”MdaBase“:”JPY“,”Mda“:”EUR“,”Fixing“:2023-05-26T00:00:00:00+01:00”,“MdaBase”:“JPY”,“Mda”:“EUR”,“Fixing”:2023-05-26T00:00:00:00+01:00“,”MdaBase“:”JPY“,”Mda“:”EUR“,”Fixing“:2023-05-26T00-00:00:00:00+01:00”,“MdaBase”:“JPY”,“Mda”:“EUR”,“Fixing”:2023-05-26T00:00:00:00:00+01:00“,”MdaBase“:”JPY“,”Mda“:”EUR“,”Fixing“:2023-05-26T00:00:00:00+01:00”,“MdaBase150.2400000000000000},{”fixingrates_ID“:4,”DtC\u00e2mbio“:”2023-05-26T00:00:00+01:00“,”MdaBase“:”SEK“,”Mda“:”EUR“,”Fixing“:11.5280000000000000},{”fixingrates_ID“:5,”DtC\u00e2mbio“:”2023-05-26T00:00:00+01:00“,”MdaBase“:”CHF“,”Mda“:”EUR“,”Fixing“:0.97070000000000000},{”fixingrates_ID“:6,”DtC\u00e2mbio“:”2023-05-26T00:00:00+01:00“,”MdaBase“:”NOK“,”Mda“:”EUR“,”Fixing“:11.8218000000000000},{”fixingrates_ID“:7,”DtC\u00e2mbio“:”2023-05-26T00:00:00+01:00“,”MdaBase“:”DKK“,”Mda“:”EUR“,”Fixing“:7.448900000000000},{”fixingrates_ID“:8,”DtC\u00e2mbio“:”2023-05-26T00:00:00+01:00“,”MdaBase“:”BRL“,”Mda“:”EUR“,”Fixing“:5.38780000000000000}]}

Índices {“@odata.context”:“http://gasgc.montepio.com/odatacustom/maintenancedata/$metadata#interestindexvalues#8f2b6731ceade8d332dec84a53057e906a421270f07a52de17d3fc5e1160c1700c454af1437737f8e674fd151e4df4ad57da7ea78a66d81aa54177609cb7fd77”,“value”:[{“interestindexvalues_ID”:1,“Indexante”:“77”,“Data”:“2023-05-25T00:00:00+01:00”,“Valor”:3.45700000,“OmitirLista”:“N”}]}

4 - 预期的根基类

public abstract class Root
{
    [JsonProperty("@odata.context")]
    public string odatacontext { get; set; }
    public abstract List<Data> value { get; set; }
}

5 - 预期的代码

    Root obj;
    switch (name)
    {
        case "Câmbios":
            obj = JsonConvert.DeserializeObject<RootCâmbios>(json);
            break;

        case "Índices":
            obj = JsonConvert.DeserializeObject<RootÍndices>(json);
            break;

        default:
            throw new InvalidOperationException($"{name} não previsto");
    }
    if (!obj.odatacontext.StartsWith($"{urlBase}/$metadata#{SGC_name}"))
          throw new InvalidOperationException("falha na validação do contexto");

    foreach (Data item in obj.value)
    {
         foreach (SqlParameter param in cmdINS.Parameters)
         {
               string paramName = param.ParameterName;
               if (!(param.ParameterName == "@RETURN_VALUE" || param.ParameterName == "@EXEC_Dia"))
                    cmdINS.Parameters[paramName].Value = item[paramName];
         }

         cmdINS.ExecuteNonQuery();
      }
C# JSON 反序列化 派生类型

评论

0赞 Ibrahim Hamaty 6/3/2023
如果没有 JSON 的模板,我们无法为您提供帮助。向我们展示 JSON 数据。
0赞 António Pragana 6/6/2023
要发送 JSON,我必须发送实际代码,否则它将不匹配,所以我编辑了帖子。

答: 暂无答案