Skip to content

Commit cd4b10b

Browse files
mikewuuseambot
andauthored
fix: add fallback for unrecognized discriminated unions (#260)
* handle unknown distinct unions * update name to unknown * revert rename to unknown * revert model updates * revert api updates * revert client updates * revert package.json * revert proj * bump generator * ci: Generate code * update types * ci: Generate code * Revert "update types" This reverts commit 48ae00a. * ci: Generate code --------- Co-authored-by: Seam Bot <seambot@getseam.com>
1 parent cd8f6ce commit cd4b10b

21 files changed

+1350
-6
lines changed

output/csharp/src/Seam.Test/Client/SeamTests.cs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,120 @@ public void TestUnknownEnumValue()
141141
device.Properties.AvailableFanModeSettings[1]
142142
);
143143
}
144+
145+
[Fact]
146+
public void TestDiscriminatedUnionArrayWithUnknownTypes()
147+
{
148+
var json =
149+
@"{
150+
""connected_account_id"": ""test-account-id"",
151+
""account_type"": ""august"",
152+
""account_type_display_name"": ""August Lock"",
153+
""automatically_manage_new_devices"": true,
154+
""created_at"": ""2024-01-15T10:00:00Z"",
155+
""accepted_capabilities"": [],
156+
""custom_metadata"": {},
157+
""errors"": [
158+
{
159+
""error_code"": ""unknown_error_type"",
160+
""message"": ""An unknown error occurred"",
161+
""created_at"": ""2024-01-15T10:00:00Z""
162+
}
163+
],
164+
""warnings"": [
165+
{
166+
""warning_code"": ""unknown_warning_type"",
167+
""message"": ""An unknown warning occurred"",
168+
""created_at"": ""2024-01-15T10:00:00Z""
169+
}
170+
]
171+
}";
172+
173+
var settings = new JsonSerializerSettings
174+
{
175+
Converters = new List<JsonConverter> { new SafeStringEnumConverter() },
176+
MissingMemberHandling = MissingMemberHandling.Ignore,
177+
};
178+
179+
// Unknown discriminated union types should fall back to unrecognized type
180+
var account = JsonConvert.DeserializeObject<ConnectedAccount>(json, settings);
181+
182+
Assert.NotNull(account);
183+
Assert.NotNull(account.Errors);
184+
Assert.Single(account.Errors);
185+
186+
// The unknown error type should fall back to an unrecognized error type
187+
var error = account.Errors[0];
188+
Assert.Equal("unrecognized", error.ErrorCode);
189+
Assert.Equal("An unknown error occurred", error.Message);
190+
}
191+
192+
[Fact]
193+
public void TestEventArrayWithUnknownTypes()
194+
{
195+
var json =
196+
@"[
197+
{
198+
""event_id"": ""event-1"",
199+
""event_type"": ""device.connected"",
200+
""created_at"": ""2024-01-15T10:00:00Z"",
201+
""occurred_at"": ""2024-01-15T10:00:00Z"",
202+
""device_id"": ""device-123"",
203+
""connected_account_id"": ""account-123"",
204+
""workspace_id"": ""workspace-123""
205+
},
206+
{
207+
""event_id"": ""event-2"",
208+
""event_type"": ""unknown_event_type"",
209+
""created_at"": ""2024-01-15T10:00:00Z"",
210+
""custom_field"": ""custom_value""
211+
}
212+
]";
213+
214+
var settings = new JsonSerializerSettings
215+
{
216+
Converters = new List<JsonConverter> { new SafeStringEnumConverter() },
217+
MissingMemberHandling = MissingMemberHandling.Ignore,
218+
};
219+
220+
// Unknown event types should fall back to unrecognized type
221+
var events = JsonConvert.DeserializeObject<List<Event>>(json, settings);
222+
223+
Assert.NotNull(events);
224+
Assert.Equal(2, events.Count);
225+
226+
// First event should deserialize normally
227+
Assert.IsType<EventDeviceConnected>(events[0]);
228+
229+
// Second event with unknown type should fall back to unrecognized
230+
var unknownEvent = events[1];
231+
Assert.IsType<EventUnrecognized>(unknownEvent);
232+
Assert.Equal("unrecognized", unknownEvent.EventType);
233+
}
234+
235+
[Fact]
236+
public void TestActionAttemptWithUnknownType()
237+
{
238+
// Test case for ActionAttempt with unknown action types
239+
var json =
240+
@"{
241+
""action_attempt_id"": ""attempt-123"",
242+
""action_type"": ""UNKNOWN_ACTION"",
243+
""status"": ""success"",
244+
""result"": {},
245+
""error"": null
246+
}";
247+
248+
var settings = new JsonSerializerSettings
249+
{
250+
Converters = new List<JsonConverter> { new SafeStringEnumConverter() },
251+
MissingMemberHandling = MissingMemberHandling.Ignore,
252+
};
253+
254+
// Unknown action types should fall back to unrecognized type
255+
var actionAttempt = JsonConvert.DeserializeObject<ActionAttempt>(json, settings);
256+
257+
Assert.NotNull(actionAttempt);
258+
Assert.Equal("unrecognized", actionAttempt.ActionType);
259+
}
144260
}

output/csharp/src/Seam/Model/AccessCode.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public AccessCode(
6464
}
6565

6666
[JsonConverter(typeof(JsonSubtypes), "error_code")]
67+
[JsonSubtypes.FallBackSubType(typeof(AccessCodeErrorsUnrecognized))]
6768
[JsonSubtypes.KnownSubType(
6869
typeof(AccessCodeErrorsBridgeDisconnected),
6970
"bridge_disconnected"
@@ -2362,6 +2363,47 @@ public override string ToString()
23622363
}
23632364
}
23642365

2366+
[DataContract(Name = "seamModel_accessCodeErrorsUnrecognized_model")]
2367+
public class AccessCodeErrorsUnrecognized : AccessCodeErrors
2368+
{
2369+
[JsonConstructorAttribute]
2370+
protected AccessCodeErrorsUnrecognized() { }
2371+
2372+
public AccessCodeErrorsUnrecognized(
2373+
string errorCode = default,
2374+
string message = default
2375+
)
2376+
{
2377+
ErrorCode = errorCode;
2378+
Message = message;
2379+
}
2380+
2381+
[DataMember(Name = "error_code", IsRequired = true, EmitDefaultValue = false)]
2382+
public override string ErrorCode { get; } = "unrecognized";
2383+
2384+
[DataMember(Name = "message", IsRequired = true, EmitDefaultValue = false)]
2385+
public override string Message { get; set; }
2386+
2387+
public override string ToString()
2388+
{
2389+
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(null);
2390+
2391+
StringWriter stringWriter = new StringWriter(
2392+
new StringBuilder(256),
2393+
System.Globalization.CultureInfo.InvariantCulture
2394+
);
2395+
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
2396+
{
2397+
jsonTextWriter.IndentChar = ' ';
2398+
jsonTextWriter.Indentation = 2;
2399+
jsonTextWriter.Formatting = Formatting.Indented;
2400+
jsonSerializer.Serialize(jsonTextWriter, this, null);
2401+
}
2402+
2403+
return stringWriter.ToString();
2404+
}
2405+
}
2406+
23652407
[JsonConverter(typeof(SafeStringEnumConverter))]
23662408
public enum StatusEnum
23672409
{
@@ -2398,6 +2440,7 @@ public enum TypeEnum
23982440
}
23992441

24002442
[JsonConverter(typeof(JsonSubtypes), "warning_code")]
2443+
[JsonSubtypes.FallBackSubType(typeof(AccessCodeWarningsUnrecognized))]
24012444
[JsonSubtypes.KnownSubType(
24022445
typeof(AccessCodeWarningsKwiksetUnableToConfirmCode),
24032446
"kwikset_unable_to_confirm_code"
@@ -3010,6 +3053,47 @@ public override string ToString()
30103053
}
30113054
}
30123055

3056+
[DataContract(Name = "seamModel_accessCodeWarningsUnrecognized_model")]
3057+
public class AccessCodeWarningsUnrecognized : AccessCodeWarnings
3058+
{
3059+
[JsonConstructorAttribute]
3060+
protected AccessCodeWarningsUnrecognized() { }
3061+
3062+
public AccessCodeWarningsUnrecognized(
3063+
string warningCode = default,
3064+
string message = default
3065+
)
3066+
{
3067+
WarningCode = warningCode;
3068+
Message = message;
3069+
}
3070+
3071+
[DataMember(Name = "warning_code", IsRequired = true, EmitDefaultValue = false)]
3072+
public override string WarningCode { get; } = "unrecognized";
3073+
3074+
[DataMember(Name = "message", IsRequired = true, EmitDefaultValue = false)]
3075+
public override string Message { get; set; }
3076+
3077+
public override string ToString()
3078+
{
3079+
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(null);
3080+
3081+
StringWriter stringWriter = new StringWriter(
3082+
new StringBuilder(256),
3083+
System.Globalization.CultureInfo.InvariantCulture
3084+
);
3085+
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
3086+
{
3087+
jsonTextWriter.IndentChar = ' ';
3088+
jsonTextWriter.Indentation = 2;
3089+
jsonTextWriter.Formatting = Formatting.Indented;
3090+
jsonSerializer.Serialize(jsonTextWriter, this, null);
3091+
}
3092+
3093+
return stringWriter.ToString();
3094+
}
3095+
}
3096+
30133097
[DataMember(Name = "access_code_id", IsRequired = true, EmitDefaultValue = false)]
30143098
public string AccessCodeId { get; set; }
30153099

output/csharp/src/Seam/Model/AccessGrant.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public AccessGrant(
5454
}
5555

5656
[JsonConverter(typeof(JsonSubtypes), "warning_code")]
57+
[JsonSubtypes.FallBackSubType(typeof(AccessGrantWarningsUnrecognized))]
5758
[JsonSubtypes.KnownSubType(typeof(AccessGrantWarningsBeingDeleted), "being_deleted")]
5859
public abstract class AccessGrantWarnings
5960
{
@@ -110,6 +111,47 @@ public override string ToString()
110111
}
111112
}
112113

114+
[DataContract(Name = "seamModel_accessGrantWarningsUnrecognized_model")]
115+
public class AccessGrantWarningsUnrecognized : AccessGrantWarnings
116+
{
117+
[JsonConstructorAttribute]
118+
protected AccessGrantWarningsUnrecognized() { }
119+
120+
public AccessGrantWarningsUnrecognized(
121+
string warningCode = default,
122+
string message = default
123+
)
124+
{
125+
WarningCode = warningCode;
126+
Message = message;
127+
}
128+
129+
[DataMember(Name = "warning_code", IsRequired = true, EmitDefaultValue = false)]
130+
public override string WarningCode { get; } = "unrecognized";
131+
132+
[DataMember(Name = "message", IsRequired = true, EmitDefaultValue = false)]
133+
public override string Message { get; set; }
134+
135+
public override string ToString()
136+
{
137+
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(null);
138+
139+
StringWriter stringWriter = new StringWriter(
140+
new StringBuilder(256),
141+
System.Globalization.CultureInfo.InvariantCulture
142+
);
143+
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
144+
{
145+
jsonTextWriter.IndentChar = ' ';
146+
jsonTextWriter.Indentation = 2;
147+
jsonTextWriter.Formatting = Formatting.Indented;
148+
jsonSerializer.Serialize(jsonTextWriter, this, null);
149+
}
150+
151+
return stringWriter.ToString();
152+
}
153+
}
154+
113155
[DataMember(Name = "access_grant_id", IsRequired = true, EmitDefaultValue = false)]
114156
public string AccessGrantId { get; set; }
115157

output/csharp/src/Seam/Model/AccessMethod.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public enum ModeEnum
6262
}
6363

6464
[JsonConverter(typeof(JsonSubtypes), "warning_code")]
65+
[JsonSubtypes.FallBackSubType(typeof(AccessMethodWarningsUnrecognized))]
6566
[JsonSubtypes.KnownSubType(typeof(AccessMethodWarningsBeingDeleted), "being_deleted")]
6667
public abstract class AccessMethodWarnings
6768
{
@@ -118,6 +119,47 @@ public override string ToString()
118119
}
119120
}
120121

122+
[DataContract(Name = "seamModel_accessMethodWarningsUnrecognized_model")]
123+
public class AccessMethodWarningsUnrecognized : AccessMethodWarnings
124+
{
125+
[JsonConstructorAttribute]
126+
protected AccessMethodWarningsUnrecognized() { }
127+
128+
public AccessMethodWarningsUnrecognized(
129+
string warningCode = default,
130+
string message = default
131+
)
132+
{
133+
WarningCode = warningCode;
134+
Message = message;
135+
}
136+
137+
[DataMember(Name = "warning_code", IsRequired = true, EmitDefaultValue = false)]
138+
public override string WarningCode { get; } = "unrecognized";
139+
140+
[DataMember(Name = "message", IsRequired = true, EmitDefaultValue = false)]
141+
public override string Message { get; set; }
142+
143+
public override string ToString()
144+
{
145+
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(null);
146+
147+
StringWriter stringWriter = new StringWriter(
148+
new StringBuilder(256),
149+
System.Globalization.CultureInfo.InvariantCulture
150+
);
151+
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
152+
{
153+
jsonTextWriter.IndentChar = ' ';
154+
jsonTextWriter.Indentation = 2;
155+
jsonTextWriter.Formatting = Formatting.Indented;
156+
jsonSerializer.Serialize(jsonTextWriter, this, null);
157+
}
158+
159+
return stringWriter.ToString();
160+
}
161+
}
162+
121163
[DataMember(Name = "access_method_id", IsRequired = true, EmitDefaultValue = false)]
122164
public string AccessMethodId { get; set; }
123165

0 commit comments

Comments
 (0)