![](/img/trans.png)
[英]How to get Sharepoint ListItem on DriveItem with Microsoft Graph API c# SDK
[英]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.