microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
samples/migration-bot

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

core/src/Microsoft.Teams.Bot.Apps/Schema/Entities/Entity.cs

167lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Text.Json;
5using System.Text.Json.Nodes;
6using System.Text.Json.Serialization;
7using Microsoft.Teams.Bot.Core.Schema;
8
9namespace Microsoft.Teams.Bot.Apps.Schema.Entities;
10
11
12/// <summary>
13/// List of Entity objects.
14/// </summary>
15[JsonConverter(typeof(EntityListJsonConverter))]
16public class EntityList : List<Entity>
17{
18 /// <summary>
19 /// Converts the Entities collection to a JsonArray.
20 /// </summary>
21 /// <returns></returns>
22 public JsonArray? ToJsonArray()
23 {
24 JsonArray jsonArray = [];
25 foreach (Entity entity in this)
26 {
27 JsonObject jsonObject = new()
28 {
29 ["type"] = entity.Type
30 };
31
32 foreach (KeyValuePair<string, object?> property in entity.Properties)
33 {
34 jsonObject[property.Key] = property.Value as JsonNode ?? JsonValue.Create(property.Value);
35 }
36 jsonArray.Add(jsonObject);
37 }
38 return jsonArray;
39 }
40
41 /// <summary>
42 /// Parses a JsonArray into an Entities collection.
43 /// </summary>
44 /// <param name="jsonArray"></param>
45 /// <param name="options"></param>
46 /// <returns></returns>
47 public static EntityList? FromJsonArray(JsonArray? jsonArray, JsonSerializerOptions? options = null)
48 {
49 if (jsonArray == null)
50 {
51 return null;
52 }
53 EntityList entities = [];
54 foreach (JsonNode? item in jsonArray)
55 {
56 if (item is JsonObject jsonObject
57 && jsonObject.TryGetPropertyValue("type", out JsonNode? typeNode)
58 && typeNode is JsonValue typeValue
59 && typeValue.GetValue<string>() is string typeString)
60 {
61
62 // TODO: Should be able to support unknown types (PA uses BotMessageMetadata).
63 // TODO: Investigate if there is any way for Parent to avoid
64 // Knowing the children.
65 // Maybe a registry pattern, or Converters?
66 Entity? entity = typeString switch
67 {
68 "clientInfo" => item.Deserialize<ClientInfoEntity>(options),
69 "mention" => item.Deserialize<MentionEntity>(options),
70 "message" or "https://schema.org/Message" => DeserializeMessageEntity(item, options),
71 "ProductInfo" => item.Deserialize<ProductInfoEntity>(options),
72 "streaminfo" => item.Deserialize<StreamInfoEntity>(options),
73 _ => null
74 };
75 if (entity != null)
76 entities.Add(entity);
77 }
78 }
79 return entities;
80 }
81
82 /// <summary>
83 /// Deserializes a message entity by checking the @type property to determine the specific type.
84 /// </summary>
85 /// <param name="item">The JSON node to deserialize.</param>
86 /// <param name="options">The JSON serializer options.</param>
87 /// <returns>The deserialized entity, or null if deserialization fails.</returns>
88 private static OMessageEntity? DeserializeMessageEntity(JsonNode item, JsonSerializerOptions? options)
89 {
90 if (item is JsonObject jsonObject
91 && jsonObject.TryGetPropertyValue("@type", out JsonNode? oTypeNode)
92 && oTypeNode is JsonValue oTypeValue
93 && oTypeValue.GetValue<string>() is string oType)
94 {
95 return oType switch
96 {
97 "Message" => item.Deserialize<CitationEntity>(options),
98 "CreativeWork" => item.Deserialize<SensitiveUsageEntity>(options),
99 _ => item.Deserialize<OMessageEntity>(options)
100 };
101 }
102
103 return item.Deserialize<OMessageEntity>(options);
104 }
105}
106
107/// <summary>
108/// Entity base class.
109/// </summary>
110/// <remarks>
111/// Initializes a new instance of the Entity class with the specified type.
112/// </remarks>
113/// <param name="type">The type of the entity. Cannot be null.</param>
114public class Entity(string type)
115{
116 /// <summary>
117 /// Gets or sets the type identifier for the object represented by this instance.
118 /// </summary>
119 [JsonPropertyName("type")]
120 public string Type { get; set; } = type;
121
122 /// <summary>
123 /// Gets or sets the OData type identifier for the object represented by this instance.
124 /// </summary>
125 [JsonPropertyName("@type")] public string? OType { get; set; }
126
127 /// <summary>
128 /// Gets or sets the OData context for the object represented by this instance.
129 /// </summary>
130 [JsonPropertyName("@context")] public string? OContext { get; set; }
131 /// <summary>
132 /// Extended properties dictionary.
133 /// </summary>
134 [JsonExtensionData] public ExtendedPropertiesDictionary Properties { get; set; } = [];
135
136}
137
138/// <summary>
139/// JSON converter for EntityList.
140/// </summary>
141public class EntityListJsonConverter : JsonConverter<EntityList>
142{
143 /// <summary>
144 /// Reads and converts the JSON to EntityList.
145 /// </summary>
146 public override EntityList? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
147 {
148 if (reader.TokenType == JsonTokenType.Null)
149 {
150 return null;
151 }
152
153 JsonArray? jsonArray = JsonSerializer.Deserialize<JsonArray>(ref reader, options);
154 return EntityList.FromJsonArray(jsonArray, options);
155 }
156
157 /// <summary>
158 /// Writes the EntityList as JSON.
159 /// </summary>
160 public override void Write(Utf8JsonWriter writer, EntityList value, JsonSerializerOptions options)
161 {
162 ArgumentNullException.ThrowIfNull(value);
163 JsonArray? jsonArray = value.ToJsonArray();
164 JsonSerializer.Serialize(writer, jsonArray, options);
165 }
166}
167
168