英文:
C# System.Text.Json Deserializing when the response format changes due to flags in the request
问题
我正在尝试使用C#和System.Text.Json来调用供应商的API。一些API调用允许在请求中添加标志,以在响应中添加部分内容。我不确定如何处理这些(因为我缺乏经验)。
如果数据格式不改变,我可以轻松地发送和接收标准类。但如何设计类来处理这些可能的部分呢?
以下是SearchItemsRequest
的类。它包含一个SearchItemsRequestSpec
,用于打包搜索项。SearchItemsRequestSpec.ItemType
决定了返回数据的基本格式。SearchItemsRequest.Flags
决定了将包括哪些部分的格式。
当执行该方法时,我目前硬编码为仅支持响应中的一种项目类型。
对于单位,可能的部分有:
在这里有一些可能的部分,其他项目类型有它们自己的部分集合。
如果这是基本的C#,我可以创建一个接口并传递它,但由于反序列化和可能缺少的部分,我肯定存在知识差距。我应该如何编写一个类来处理项目返回数据的所有可能排列呢?
英文:
I'm trying to consume a vendor's api using c# and System.Text.Json. Some API calls allow for flags in the request that add sections to the response. I'm not sure how to handle these (lack of experience).
I can send and receive no problem to standard classes if the format doesn't change. How do I design classes to handle these possible sections?
Following are the classes for a SearchItemsRequest
. It contains a SearchItemsRequestSpec
that bundles up the search terms. The SearchItemsRequestSpec.ItemType
governs the base format of the data returned. The SearchItemsRequest.Flags
governs the sections that will be included of that format.
/// <summary>
/// Constructor. Sets up for a new search that will return all items.
/// </summary>
public SearchItemsRequest()
{
Spec = new SearchItemsRequestSpec();
Force = SearchItemsForce.NewSearch;
Flags = 1; // basic response
From = 0; // for new search use 0
To = 0; // return all elements beginning from index specified in the “from” parameter
}
/// <summary>
/// Search Specification
/// </summary>
[JsonPropertyName("spec")]
public SearchItemsRequestSpec Spec { get; set; }
/// <summary>
/// 0 - if such search has been done, then return cached result, 1 - to do a new search
/// </summary>
[JsonPropertyName("force")]
public SearchItemsForce Force { get; set; }
/// <summary>
/// Data flags for the response
/// <para>
/// The value of this parameter depends on item type; data formats of all item types and their flags are described in the chapter <see href="https://sdk.wialon.com/wiki/en/sidebar/remoteapi/apiref/format/format">Data format</see>
/// </para>
/// </summary>
[JsonPropertyName("flags")]
public long Flags { get; set; }
/// <summary>
/// index of the first returned item (for new search use 0)
/// </summary>
[JsonPropertyName("from")]
public uint From { get; set; }
/// <summary>
/// index of the last returned item (if 0 - return all elements beginning from index specified in the “from” parameter)
/// </summary>
[JsonPropertyName("to")]
public uint To { get; set; }
}
/// <summary>
/// Search Criteria
/// <para>
/// <see cref="https://sdk.wialon.com/wiki/en/sidebar/remoteapi/apiref/core/search_items">Search Items API Ref</see>
/// </para>
/// <para>
/// Multi-criteria search is possible<br/>
/// {"itemsType":"avl_unit","propName":"sys_name,rel_user_creator_name","propValueMask":"Volvo*,chdi_test","sortType":"sys_name","propType":"sys_name,rel_user_creator_name","or_logic":0}
/// </para>
/// </summary>
public class SearchItemsRequestSpec
{
/// <summary>
/// Constructor. Defaults are to search for units by unique id
/// </summary>
public SearchItemsRequestSpec()
{
ItemsType = SearchItemsItemType.avl_unit;
PropName = SearchItemsPropName.sys_unique_id;
PropValueMask = string.Empty;
SortType = SearchItemsPropName.sys_unique_id;
PropType = SearchItemsPropType.property;
OrLogic = SearchItemsOrLogic.Disabled;
}
[JsonPropertyName("itemsType")]
public SearchItemsItemType ItemsType { get; set; }
[JsonPropertyName("propName")]
public SearchItemsPropName PropName { get; set; }
[JsonPropertyName("propValueMask")]
public string PropValueMask { get; set; }
/// <summary>
/// Uses the same enum as PropName. Not a typo
/// </summary>
[JsonPropertyName("sortType")]
public SearchItemsPropName SortType { get; set; }
[JsonPropertyName("propType")]
public SearchItemsPropType PropType { get; set; }
[JsonPropertyName("or_logic")]
public SearchItemsOrLogic OrLogic { get; set; }
}
When executing the method, I'm currently hardcoded to only support one item type in the response
internal class SearchItemsResponse
{
[JsonPropertyName("searchSpec")]
public SearchItemsResponseSpec SearchSpec { get; set; }
[JsonPropertyName("dataFlags")]
public uint DataFlags { get; set; }
[JsonPropertyName("totalItemsCount")]
public uint TotalItemsCount { get; set; }
[JsonPropertyName("indexFrom")]
public uint IndexFrom { get; set; }
[JsonPropertyName("indexTo")]
public uint IndexTo { get; set; }
[JsonPropertyName("items")]
public List<Item_UnitBasic> Items { get; set; } //basic data for unit only
}
the possible sections for a unit are
[Flags]
internal enum UnitResponseFlags : long
{
BaseFlag = 1, // 0x00000001
CustomProperties = 2, // 0x00000002
BillingProperties = 4, // 0x00000004
CustomFields = 8, // 0x00000008
Image = 16, // 0x00000010
Messages = 32, // 0x00000020
GUID = 64, // 0x00000040
AdministrativeFields = 128, // 0x00000080
AdvancedProperties = 256, // 0x00000100
AvailableForCurrentMomentCommands = 512, // 0x00000200
LastMessageAndPosition = 1024, // 0x00000400
Sensors = 4096, // 0x00001000
Counters = 8192, // 0x00002000
Maintenance = 32768, // 0x00008000
UnitConfigurationInReports = 131072, // 0x00020000 - trip detector and fuel consumption
ListAllPossibleCommandsForCurrentUnit = 524288, // 0x00080000
MessageParameters = 1048576, // 0x00100000
UnitConnectionStatus = 2097152, // 0x00200000
Position = 4194304, // 0x00400000
ProfileFields = 8388608, // 0x00800000
SetAllPossibleFlags = 4611686018427387903 // 0x3FFFFFFFFFFFFFFF
}
There's a few, and the other item types have their own collections of sections.
If this was basic c#, I'd create an interface and pass that around, but with the deserialization and the possible missing sections, I definitely have a knowledge gap. How do I write a class to handle all the possible permutations of returned data for an item?
答案1
得分: 0
你可以使用JsonDocument来处理那些不容易映射到静态模型的 JSON 数据。<br>
(不要忘记在完成后释放文档,因为它使用了池内存)
英文:
You can use JsonDocument for json that can not easily be mapped to a static model.<br>
(Don't forget to dispose the document when you are done with it as it uses pooled memory)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论