microsoft/teams.net

Public

mirrored from https://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
mehak/state

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

168lines · 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.Core.Schema;
8
9namespace Microsoft.Teams.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 // TODO: Should be able to support unknown types (PA uses BotMessageMetadata).
62 // TODO: Investigate if there is any way for Parent to avoid
63 // Knowing the children.
64 // Maybe a registry pattern, or Converters?
65 Entity? entity = typeString switch
66 {
67 "clientInfo" => item.Deserialize<ClientInfoEntity>(options),
68 "mention" => item.Deserialize<MentionEntity>(options),
69 "message" or "https://schema.org/Message" => DeserializeMessageEntity(item, options),
70 "ProductInfo" => item.Deserialize<ProductInfoEntity>(options),
71 "streaminfo" => item.Deserialize<StreamInfoEntity>(options),
72 "quotedReply" => item.Deserialize<QuotedReplyEntity>(options),
73 "targetedMessageInfo" => item.Deserialize<TargetedMessageInfoEntity>(options),
74 _ => item.Deserialize<Entity>(options)
75 };
76 if (entity != null)
77 entities.Add(entity);
78 }
79 }
80 return entities;
81 }
82
83 /// <summary>
84 /// Deserializes a message entity by checking the @type property to determine the specific type.
85 /// </summary>
86 /// <param name="item">The JSON node to deserialize.</param>
87 /// <param name="options">The JSON serializer options.</param>
88 /// <returns>The deserialized entity, or null if deserialization fails.</returns>
89 private static OMessageEntity? DeserializeMessageEntity(JsonNode item, JsonSerializerOptions? options)
90 {
91 if (item is JsonObject jsonObject
92 && jsonObject.TryGetPropertyValue("@type", out JsonNode? oTypeNode)
93 && oTypeNode is JsonValue oTypeValue
94 && oTypeValue.GetValue<string>() is string oType)
95 {
96 return oType switch
97 {
98 "Message" => item.Deserialize<CitationEntity>(options),
99 "CreativeWork" => item.Deserialize<SensitiveUsageEntity>(options),
100 _ => item.Deserialize<OMessageEntity>(options)
101 };
102 }
103
104 return item.Deserialize<OMessageEntity>(options);
105 }
106}
107
108/// <summary>
109/// Entity base class.
110/// </summary>
111/// <remarks>
112/// Initializes a new instance of the Entity class with the specified type.
113/// </remarks>
114/// <param name="type">The type of the entity. Cannot be null.</param>
115public class Entity(string type)
116{
117 /// <summary>
118 /// Gets or sets the type identifier for the object represented by this instance.
119 /// </summary>
120 [JsonPropertyName("type")]
121 public string Type { get; set; } = type;
122
123 /// <summary>
124 /// Gets or sets the OData type identifier for the object represented by this instance.
125 /// </summary>
126 [JsonPropertyName("@type")] public string? OType { get; set; }
127
128 /// <summary>
129 /// Gets or sets the OData context for the object represented by this instance.
130 /// </summary>
131 [JsonPropertyName("@context")] public string? OContext { get; set; }
132 /// <summary>
133 /// Extended properties dictionary.
134 /// </summary>
135 [JsonExtensionData] public ExtendedPropertiesDictionary Properties { get; set; } = [];
136
137}
138
139/// <summary>
140/// JSON converter for EntityList.
141/// </summary>
142public class EntityListJsonConverter : JsonConverter<EntityList>
143{
144 /// <summary>
145 /// Reads and converts the JSON to EntityList.
146 /// </summary>
147 public override EntityList? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
148 {
149 if (reader.TokenType == JsonTokenType.Null)
150 {
151 return null;
152 }
153
154 JsonArray? jsonArray = JsonSerializer.Deserialize<JsonArray>(ref reader, options);
155 return EntityList.FromJsonArray(jsonArray, options);
156 }
157
158 /// <summary>
159 /// Writes the EntityList as JSON.
160 /// </summary>
161 public override void Write(Utf8JsonWriter writer, EntityList value, JsonSerializerOptions options)
162 {
163 ArgumentNullException.ThrowIfNull(value);
164 JsonArray? jsonArray = value.ToJsonArray();
165 JsonSerializer.Serialize(writer, jsonArray, options);
166 }
167}
168
169