3

我正在尝试使用 c# 和 json.net反序列化来自 OctoPart API ( http://octopart.com/api/docs/v3/rest-api ) 的结果

反序列化大部分数据没有问题,但是我遇到了 Part.specs 属性(http://octopart.com/api/docs/v3/rest-api#notes-part.specs)的问题,因为这些属性根据返回的项目更改。

以下是 API 关于 Part.Specs 的说明

附加到 Part 实例的 specs 属性是一个 JSON 对象映射属性短名称(例如“voltage_rating_dc”)到QualitativeValueQuantitativeValue实例。
请务必注意, (Qual|Quant)itativeValue 对象的所有值属性都是 JSON 数组。这样做的原因是为了适应多值属性,例如具有多个输出电压的电源:

因为我想维护类,我相信我可能需要实现一个自定义的 JConverter?我在看这个问题,但不太确定如何应用于此示例,因为属性可以反序列化为 QualitativeValue / QuantitativeValue 类

这是我的部分课程

public class Part
{
    public string __class__ { get; set; }
    public string uid { get; set; }
    public long uid_v2 { get; set; }
    public string mpn { get; set; }
    public Manufacturer manufacturer { get; set; }
    public Brand brand { get; set; }
    public string octopart_url { get; set; }
    public List<PartOffer> offers { get; set; }
    public List<Datasheet> datasheets { get; set; }
    public List<ComplianceDocument> compliance_documents { get; set; }
    public List<Description> descriptions { get; set; }
    public List<ImageSet> imagesets { get; set; }
    public Dictionary<string, string> specs { get; set; }
    public List<string> category_uids { get; set; }
    public List<ExternalLinks> external_links { get; set; }
}

这是来自 API 的示例结果 (PartsMatchResponse)

{
    "__class__": "PartsMatchResponse",
    "msec": 183,
    "request": {
        "__class__": "PartsMatchRequest",
        "exact_only": false,
        "queries": [
            {
                "__class__": "PartsMatchQuery",
                "brand": null,
                "limit": 10,
                "mpn": "ERJ8BWFR010V",
                "mpn_or_sku": null,
                "q": "",
                "reference": null,
                "seller": null,
                "sku": null,
                "start": 0
            }
        ]
    },
    "results": [
        {
            "__class__": "PartsMatchResult",
            "error": null,
            "hits": 1,
            "items": [
                {
                    "__class__": "Part",
                    "brand": {
                        "__class__": "Brand",
                        "name": "Panasonic - ECG",
                        "uid": "4c528d5878c09b95"
                    },
                    "category_uids": [
                        "7542b8484461ae85",
                        "cd01000bfc2916c6",
                        "5c6a91606d4187ad"
                    ],
                    "compliance_documents": [],
                    "datasheets": null,
                    "external_links": {
                        "__class__": "ExternalLinks",
                        "evalkit_url": null,
                        "freesample_url": null,
                        "product_url": null
                    },
                    "imagesets": null,
                    "manufacturer": {
                        "__class__": "Manufacturer",
                        "name": "Panasonic - ECG",
                        "uid": "c20a0700af7c11cd"
                    },
                    "mpn": "ERJ8BWFR010V",
                    "octopart_url": "http://octopart.com/erj8bwfr010v-panasonic+-+ecg-7979066",
                    "offers": null,
                    "specs": {
                        "case_package": {
                            "__class__": "QualitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": []
                            },
                            "value": [
                                "1206"
                            ]
                        },
                        "case_package_si": {
                            "__class__": "QualitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": []
                            },
                            "value": [
                                "3216"
                            ]
                        },
                        "lead_free_status": {
                            "__class__": "QualitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": [
                                    {
                                        "__class__": "Source",
                                        "name": "Future Electronics",
                                        "uid": "e4032109c4f337c4"
                                    }
                                ]
                            },
                            "value": [
                                "Lead Free"
                            ]
                        },
                        "lifecycle_status": {
                            "__class__": "QualitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": []
                            },
                            "value": [
                                "Not Listed by Manufacturer"
                            ]
                        },
                        "pin_count": {
                            "__class__": "QuantitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": [
                                    {
                                        "__class__": "Source",
                                        "name": "Farnell",
                                        "uid": "58989d9272cd8b5f"
                                    }
                                ]
                            },
                            "max_value": null,
                            "min_value": null,
                            "unit": null,
                            "value": [
                                "2"
                            ]
                        },
                        "power_rating": {
                            "__class__": "QuantitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": [
                                    {
                                        "__class__": "Source",
                                        "name": "Newark",
                                        "uid": "d294179ef2900153"
                                    }
                                ]
                            },
                            "max_value": null,
                            "min_value": null,
                            "unit": null,
                            "value": [
                                "0.5"
                            ]
                        },
                        "resistance": {
                            "__class__": "QuantitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": [
                                    {
                                        "__class__": "Source",
                                        "name": "Farnell",
                                        "uid": "58989d9272cd8b5f"
                                    }
                                ]
                            },
                            "max_value": null,
                            "min_value": null,
                            "unit": null,
                            "value": [
                                "0.01"
                            ]
                        },
                        "resistance_tolerance": {
                            "__class__": "QualitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": []
                            },
                            "value": [
                                "\u00b11%"
                            ]
                        },
                        "rohs_status": {
                            "__class__": "QualitativeValue",
                            "attribution": {
                                "__class__": "Attribution",
                                "first_acquired": null,
                                "sources": [
                                    {
                                        "__class__": "Source",
                                        "name": "Newark",
                                        "uid": "d294179ef2900153"
                                    }
                                ]
                            },
                            "value": [
                                "Compliant"
                            ]
                        }
                    },
                    "uid": "69e8a09b8cb4b62f",
                    "uid_v2": 797906654705
                }
            ],
            "reference": null
        }
    ]
}
4

2 回答 2

1

是的,你需要一个定制JsonConverter来解决这个问题。基本上你需要做的是:

  1. 定义您的QualitativeValueQuantitativeValue类以具有公共基类(例如AbstractQValue)或接口。
  2. 在您的Parts班级中,将specs属性设为 a Dictionary<string, AbstractQValue>。这将处理不断变化的属性名称。
  3. 创建一个自定义JsonConverter来处理具体的实例化QualitativeValueQuantitativeValue基于__class__JSON 中的属性。有关如何实现此功能的示例,请参见此答案。
  4. 最后,当您进行反序列化时,请务必将自定义实例传递JsonConverterJsonConvert.DeserializeObject方法。

演示

我有一点时间,所以我整理了一个工作示例。以下是数据的类定义(为简洁起见,我删除了大部分无关的内容):

public class PartsMatchResponse
{
    public List<PartsMatchResult> results { get; set; }
}

public class PartsMatchResult
{
    public List<Part> items { get; set; }
}

public class Part
{
    public Manufacturer manufacturer { get; set; }
    public string mpn { get; set; }
    public Dictionary<string, AbstractQValue> specs { get; set; }
}

public class Manufacturer
{
    public string name { get; set; }
}

public abstract class AbstractQValue
{
    public List<string> value { get; set; }
}

public class QualitativeValue : AbstractQValue
{
}

public class QuantitativeValue : AbstractQValue
{
    public string unit { get; set; }
}

这是自定义JsonConverter类:

public class QValueJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(AbstractQValue).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, 
        Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        if (jo["__class__"].ToString() == "QuantitativeValue")
        {
            return jo.ToObject<QuantitativeValue>();
        }
        return jo.ToObject<QualitativeValue>();
    }

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

这是一个演示程序,展示了在反序列化时如何使用转换器:

class Program
{
    static void Main(string[] args)
    {
        // (jsonString is defined as a constant below)

        PartsMatchResponse response = 
            JsonConvert.DeserializeObject<PartsMatchResponse>(jsonString, 
                new QValueJsonConverter());

        foreach (Part part in response.results[0].items)
        {
            Console.WriteLine("manufacturer: " + part.manufacturer.name);
            Console.WriteLine("mfr. part no: " + part.mpn);
            foreach (KeyValuePair<string, AbstractQValue> kvp in part.specs)
            {
                string unit = "";
                if (kvp.Value is QuantitativeValue) 
                    unit = ((QuantitativeValue)kvp.Value).unit;

                Console.WriteLine(kvp.Key + ": " + 
                    string.Join(", ", kvp.Value.value) + " " + unit);
            }
            Console.WriteLine();
        }
    }

    // Note: this is the same as the example JSON in the question, except 
    // I added units for some of the QuantitativeValue specs for demo purposes.

    const string jsonString = @"
        {
            ""__class__"": ""PartsMatchResponse"",
            ""msec"": 183,
            ""request"": {
                ""__class__"": ""PartsMatchRequest"",
                ""exact_only"": false,
                ""queries"": [
                    {
                        ""__class__"": ""PartsMatchQuery"",
                        ""brand"": null,
                        ""limit"": 10,
                        ""mpn"": ""ERJ8BWFR010V"",
                        ""mpn_or_sku"": null,
                        ""q"": """",
                        ""reference"": null,
                        ""seller"": null,
                        ""sku"": null,
                        ""start"": 0
                    }
                ]
            },
            ""results"": [
                {
                    ""__class__"": ""PartsMatchResult"",
                    ""error"": null,
                    ""hits"": 1,
                    ""items"": [
                        {
                            ""__class__"": ""Part"",
                            ""brand"": {
                                ""__class__"": ""Brand"",
                                ""name"": ""Panasonic - ECG"",
                                ""uid"": ""4c528d5878c09b95""
                            },
                            ""category_uids"": [
                                ""7542b8484461ae85"",
                                ""cd01000bfc2916c6"",
                                ""5c6a91606d4187ad""
                            ],
                            ""compliance_documents"": [],
                            ""datasheets"": null,
                            ""external_links"": {
                                ""__class__"": ""ExternalLinks"",
                                ""evalkit_url"": null,
                                ""freesample_url"": null,
                                ""product_url"": null
                            },
                            ""imagesets"": null,
                            ""manufacturer"": {
                                ""__class__"": ""Manufacturer"",
                                ""name"": ""Panasonic - ECG"",
                                ""uid"": ""c20a0700af7c11cd""
                            },
                            ""mpn"": ""ERJ8BWFR010V"",
                            ""octopart_url"": ""http://octopart.com/erj8bwfr010v-panasonic+-+ecg-7979066"",
                            ""offers"": null,
                            ""specs"": {
                                ""case_package"": {
                                    ""__class__"": ""QualitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": []
                                    },
                                    ""value"": [
                                        ""1206""
                                    ]
                                },
                                ""case_package_si"": {
                                    ""__class__"": ""QualitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": []
                                    },
                                    ""value"": [
                                        ""3216""
                                    ]
                                },
                                ""lead_free_status"": {
                                    ""__class__"": ""QualitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": [
                                            {
                                                ""__class__"": ""Source"",
                                                ""name"": ""Future Electronics"",
                                                ""uid"": ""e4032109c4f337c4""
                                            }
                                        ]
                                    },
                                    ""value"": [
                                        ""Lead Free""
                                    ]
                                },
                                ""lifecycle_status"": {
                                    ""__class__"": ""QualitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": []
                                    },
                                    ""value"": [
                                        ""Not Listed by Manufacturer""
                                    ]
                                },
                                ""pin_count"": {
                                    ""__class__"": ""QuantitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": [
                                            {
                                                ""__class__"": ""Source"",
                                                ""name"": ""Farnell"",
                                                ""uid"": ""58989d9272cd8b5f""
                                            }
                                        ]
                                    },
                                    ""max_value"": null,
                                    ""min_value"": null,
                                    ""unit"": null,
                                    ""value"": [
                                        ""2""
                                    ]
                                },
                                ""power_rating"": {
                                    ""__class__"": ""QuantitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": [
                                            {
                                                ""__class__"": ""Source"",
                                                ""name"": ""Newark"",
                                                ""uid"": ""d294179ef2900153""
                                            }
                                        ]
                                    },
                                    ""max_value"": null,
                                    ""min_value"": null,
                                    ""unit"": ""Watt"",
                                    ""value"": [
                                        ""0.5""
                                    ]
                                },
                                ""resistance"": {
                                    ""__class__"": ""QuantitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": [
                                            {
                                                ""__class__"": ""Source"",
                                                ""name"": ""Farnell"",
                                                ""uid"": ""58989d9272cd8b5f""
                                            }
                                        ]
                                    },
                                    ""max_value"": null,
                                    ""min_value"": null,
                                    ""unit"": ""Ohm"",
                                    ""value"": [
                                        ""0.01""
                                    ]
                                },
                                ""resistance_tolerance"": {
                                    ""__class__"": ""QualitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": []
                                    },
                                    ""value"": [
                                        ""\u00b11%""
                                    ]
                                },
                                ""rohs_status"": {
                                    ""__class__"": ""QualitativeValue"",
                                    ""attribution"": {
                                        ""__class__"": ""Attribution"",
                                        ""first_acquired"": null,
                                        ""sources"": [
                                            {
                                                ""__class__"": ""Source"",
                                                ""name"": ""Newark"",
                                                ""uid"": ""d294179ef2900153""
                                            }
                                        ]
                                    },
                                    ""value"": [
                                        ""Compliant""
                                    ]
                                }
                            },
                            ""uid"": ""69e8a09b8cb4b62f"",
                            ""uid_v2"": 797906654705
                        }
                    ],
                    ""reference"": null
                }
            ]
        }";
}

最后,这是上述程序的输出:

manufacturer: Panasonic - ECG
mfr. part no: ERJ8BWFR010V
case_package: 1206
case_package_si: 3216
lead_free_status: Lead Free
lifecycle_status: Not Listed by Manufacturer
pin_count: 2
power_rating: 0.5 Watt
resistance: 0.01 Ohm
resistance_tolerance: ±1%
rohs_status: Compliant
于 2013-10-16T14:19:13.127 回答
0

您将需要这些类来为 JSON 建模

public class OctopartObject
{
    public string __class__ { get; set; }
    public int msec { get; set; }
    public Request request { get; set; }
    public List<Result> results { get; set; }
}

public class Query
{
    public string __class__ { get; set; }
    public object brand { get; set; }
    public int limit { get; set; }
    public string mpn { get; set; }
    public object mpn_or_sku { get; set; }
    public string q { get; set; }
    public object reference { get; set; }
    public object seller { get; set; }
    public object sku { get; set; }
    public int start { get; set; }
}

public class Request
{
    public string __class__ { get; set; }
    public bool exact_only { get; set; }
    public List<Query> queries { get; set; }
}

public class Brand
{
    public string __class__ { get; set; }
    public string name { get; set; }
    public string uid { get; set; }
}

public class Manufacturer
{
    public string __class__ { get; set; }
    public string name { get; set; }
    public string uid { get; set; }
}

public class Item
{
    public string __class__ { get; set; }
    public Brand brand { get; set; }
    public Manufacturer manufacturer { get; set; }
    public string mpn { get; set; }
    public string octopart_url { get; set; }
    public List<object> offers { get; set; }
    public string uid { get; set; }
    public object uid_v2 { get; set; }
}

public class Result
{
    public string __class__ { get; set; }
    public object error { get; set; }
    public int hits { get; set; }
    public List<Item> items { get; set; }
    public object reference { get; set; }
}

然后使用 JSON.NET & .NET 4.5,做这样的事情。

HttpClient client = new HttpClient();

// Send a request asynchronously and continue when complete
HttpResponseMessage clientResult = await client.GetAsync(_address);

// Check that response was successful or throw exception
clientResult.EnsureSuccessStatusCode();

// Read response asynchronously as JToken and write out top facts for each country
string jsonString = await clientResult.Content.ReadAsStringAsync();

OctopartObject obj = JsonConvert.DeserializeObject<OctopartObject>(jsonString);

您将拥有一个不错的对象,该对象应该对从 _address URI 接收的数据进行建模

我还没有完全测试这个,所以可能有一些问题。但是我已经为此苦苦挣扎了几个小时,终于找到了似乎可行的方法。我确信它不适用于数据表和任何额外的字段,因为这只返回基本的。但我基本上只是使用这个站点来获取对象模型并将根的名称更改为 OctopartObject

于 2013-10-28T22:13:40.480 回答