簡體   English   中英

將 Microsoft Graph ListItem 輸出轉換為相應的 C# 類型

[英]Transforming Microsoft Graph ListItem Output to a corresponding C# type

通過 SharePoint 和 MS Graph 提供的“幫助”組合,將 JSON 數據轉換為類型化數據模型的工作似乎變得更加復雜。 :-)

我在 Microsoft 365 中有一個 SharePoint 列表,我正在通過 C# 中的圖形 API 訪問它,其中查詢目標是一個類型化的類,其屬性與 SharePoint 列表列屬性相同。

ListItem類 Graph API 在類型為Dictionary<string,object{System.Text.Json.JsonElement}>Fields.AdditionalData中返回結果它需要成為一個IEnumerable<DataItem> ,我可以通過從中獲取 List通過序列化/反序列化往返查詢結果,如下:

var backToJSON = ListItems.Select(o => System.Text.Json.JsonSerializer.Serialize(o.Fields.AdditionalData));
var stronglyTypedItems = backToJSON.Select(jsonO => System.Text.Json.JsonSerializer.Deserialize<DataItem>(jsonO));

有沒有辦法做到這一點,無論是使用更智能的 OData 還是我從未見過的 Graph API 中的東西,而無需采用以前的 JSON 並通過 JSON 序列化程序將其發送回兩次?

更多詳細信息如下:來自 Graph Explorer 的示例輸出 JSON,其中value包含一個數組:

"value" : [ 
    { "id": "1001, 
      "fields": { 
        "Column" : "true", 
        "Column2" : "value2", 
        "Column3" : "65" 
      } 
    }, 
    { "id": "1002, 
      "fields": { 
  <and so forth until the array terminates>
  ]
}

對應的 C# 類(字面上使用“將 JSON 粘貼為類”構建):

Public class DataItem {
  public bool Column {get; set;}
  public string Column2 {get; set;}
  public int Column3 {get; set;}
}

C# Graph API 中的“Helper”類主要轉換為我實際需要的字段數組:

        private static GraphServiceClient graphClient;

        public static IListItemsCollectionRequest LicenseExpirationsList => graphClient
            .Sites["<guid>"]
            .Lists["<nameOfList>"].Items
            .Request()
            .Header("Accept", "application/json;odata.metadata=none")
            .Select("fields,id")
            .Expand("fields");

            var ListItems = (await GraphHelper.LicenseExpirationsList.GetAsync()).CurrentPage;


// JSON round tripping through JSONSerializer to get the strong type...
// But why? ListItems.Fields.AdditionalData is a Dictionary of JSON elements in the first place!

            var backToJSON = ListItems.Select(o => System.Text.Json.JsonSerializer.Serialize(o.Fields.AdditionalData));
            var stronglyTypedItems = backToJSON.Select(jsonO => System.Text.Json.JsonSerializer.Deserialize<DataItem>(jsonO));
 

            return stronglyTypedItems;

如果您不介意往返序列化,則可以自定義客戶端的 JSON 序列化

// Use custom JSON converter when deserializing response
var serializerOptions = new JsonSerializerOptions();
serializerOptions.Converters.Add(new CustomFieldValueSetJsonConverter());

var responseSerializer = new Serializer(serializerOptions);
var responseHandler = new ResponseHandler(responseSerializer);

var request = (ListItemsCollectionRequest)client.Sites[""].Lists[""].Items.Request();

var listItems = await request
    .WithResponseHandler(responseHandler)
    .GetAsync();

實現自定義 JSON 轉換器:

class CustomFieldValueSetJsonConverter : JsonConverter<FieldValueSet>
{
    private static readonly JsonEncodedText ODataTypeProperty
        = JsonEncodedText.Encode("@odata.type");
    private static readonly JsonEncodedText IdProperty 
        = JsonEncodedText.Encode("id");
    private static readonly JsonEncodedText ColumnProperty 
        = JsonEncodedText.Encode("Column");
    private static readonly JsonEncodedText Column2Property 
        = JsonEncodedText.Encode("Column2");
    private static readonly JsonEncodedText Column3Property
        = JsonEncodedText.Encode("Column3");

    public override FieldValueSet Read(ref Utf8JsonReader reader, 
        Type typeToConvert, JsonSerializerOptions options)
    {
        var result = new FieldValueSet();
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;

        foreach (var element in root.EnumerateObject())
        {
            // Set OData type property
            if (element.NameEquals(ODataTypeProperty.EncodedUtf8Bytes))
            {
                result.ODataType = element.Value.GetString();
            }
            // Set Id property
            else if (element.NameEquals(IdProperty.EncodedUtf8Bytes))
            {
                result.Id = element.Value.GetString();
            }
            // Create DataItem in AdditionalData
            else if (element.NameEquals(ColumnProperty.EncodedUtf8Bytes)
                || element.NameEquals(Column2Property.EncodedUtf8Bytes)
                || element.NameEquals(Column3Property.EncodedUtf8Bytes))
            {
                result.AdditionalData ??= new Dictionary<string, object>();
                if (!result.AdditionalData.ContainsKey("DataItem"))
                {
                    result.AdditionalData.Add("DataItem", new DataItem());
                }

                var dataItem = (DataItem)result.AdditionalData["DataItem"];
                if (element.NameEquals(ColumnProperty.EncodedUtf8Bytes))
                {
                    dataItem.Column = element.Value.GetBoolean();
                }
                else if (element.NameEquals(ColumnProperty.EncodedUtf8Bytes))
                {
                    dataItem.Column2 = element.Value.GetString();
                }
                else if (element.NameEquals(ColumnProperty.EncodedUtf8Bytes))
                {
                    dataItem.Column3 = element.Value.GetInt32();
                }
            }
        }

        return result;
    }

    public override void Write(Utf8JsonWriter writer, 
        FieldValueSet value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}

要訪問DataItem對象:

var dataItem = (DataItem)listItem.Fields.AdditionalData["DataItem"];

您可能會發現 GraphServiceClient 的HttpProvider在這種情況下很有幫助:

        var listItemsCollectionRequest = graphServiceClient
         .Sites["<guid>"]
         .Lists["<nameOfList>"]
         .Items
         .Request()
         .Header("Accept", "application/json;odata.metadata=none")
         .Select("fields,id")
         .Expand("fields");

        using (var requestMessage = listItemsCollectionRequest.GetHttpRequestMessage())
        {
            using var responseMessage = await graphServiceClient.HttpProvider.SendAsync(requestMessage);

            //deserialize the response body into DataItem
        }

通過使用 HttpProvider,您可以直接處理來自 Graph API 的響應並將響應正文反序列化為您的自定義類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM