1
- using Newtonsoft.Json;
2
- using Newtonsoft.Json.Converters;
3
- using Newtonsoft.Json.Linq;
4
- using Newtonsoft.Json.Serialization;
5
1
using System;
6
2
using System.Collections.Generic;
7
3
using System.IO;
8
4
using System.Linq;
9
5
using System.Net.Http;
10
6
using System.Net.Http.Headers;
11
7
using System.Text;
8
+ using System.Text.Json;
9
+ using System.Text.Json.Serialization;
12
10
using System.Threading.Tasks;
13
11
using {{ spec .title | caseUcfirst }}.Converters;
14
12
using {{ spec .title | caseUcfirst }}.Extensions;
@@ -29,26 +27,28 @@ namespace {{ spec.title | caseUcfirst }}
29
27
30
28
private static readonly int ChunkSize = 5 * 1024 * 1024;
31
29
32
- public static JsonSerializerSettings DeserializerSettings { get; set; } = new JsonSerializerSettings
30
+ public static JsonSerializerOptions DeserializerOptions { get; set; } = new JsonSerializerOptions
33
31
{
34
- MetadataPropertyHandling = MetadataPropertyHandling.Ignore ,
35
- NullValueHandling = NullValueHandling.Ignore ,
36
- ContractResolver = new CamelCasePropertyNamesContractResolver() ,
37
- Converters = new List< JsonConverter >
32
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase ,
33
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull ,
34
+ PropertyNameCaseInsensitive = true ,
35
+ Converters =
38
36
{
39
- new StringEnumConverter(new CamelCaseNamingStrategy()),
40
- new ValueClassConverter()
37
+ new JsonStringEnumConverter(JsonNamingPolicy.CamelCase),
38
+ new ValueClassConverter(),
39
+ new ObjectToInferredTypesConverter()
41
40
}
42
41
};
43
42
44
- public static JsonSerializerSettings SerializerSettings { get; set; } = new JsonSerializerSettings
43
+ public static JsonSerializerOptions SerializerOptions { get; set; } = new JsonSerializerOptions
45
44
{
46
- NullValueHandling = NullValueHandling.Ignore ,
47
- ContractResolver = new CamelCasePropertyNamesContractResolver() ,
48
- Converters = new List< JsonConverter >
45
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase ,
46
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull ,
47
+ Converters =
49
48
{
50
- new StringEnumConverter(new CamelCaseNamingStrategy()),
51
- new ValueClassConverter()
49
+ new JsonStringEnumConverter(JsonNamingPolicy.CamelCase),
50
+ new ValueClassConverter(),
51
+ new ObjectToInferredTypesConverter()
52
52
}
53
53
};
54
54
@@ -69,14 +69,14 @@ namespace {{ spec.title | caseUcfirst }}
69
69
_headers = new Dictionary<string , string >()
70
70
{
71
71
{ "content-type", "application/json" },
72
- { "user-agent" , "{{spec .title | caseUcfirst }}{{ language .name | caseUcfirst }}SDK/{{ sdk .version }} ($ {Environment.OSVersion.Platform}; $ {Environment.OSVersion.VersionString})"},
72
+ { "user-agent" , $ "{{spec .title | caseUcfirst }}{{ language .name | caseUcfirst }}SDK/{{ sdk .version }} ({Environment.OSVersion.Platform}; {Environment.OSVersion.VersionString})"},
73
73
{ "x-sdk-name", "{{ sdk .name }}" },
74
74
{ "x-sdk-platform", "{{ sdk .platform }}" },
75
75
{ "x-sdk-language", "{{ language .name | caseLower }}" },
76
- { "x-sdk-version", "{{ sdk .version }}"}{% if spec .global .defaultHeaders | length > 0 %},{% endif %}
76
+ { "x-sdk-version", "{{ sdk .version }}"}{% if spec .global .defaultHeaders | length > 0 %},
77
77
{%~ for key ,header in spec .global .defaultHeaders %}
78
78
{ "{{key }}", "{{header }}" }{% if not loop .last %},{% endif %}
79
- {%~ endfor %}
79
+ {%~ endfor %}{% endif %}
80
80
81
81
};
82
82
@@ -86,8 +86,6 @@ namespace {{ spec.title | caseUcfirst }}
86
86
{
87
87
SetSelfSigned(true);
88
88
}
89
-
90
- JsonConvert.DefaultSettings = () => DeserializerSettings;
91
89
}
92
90
93
91
public Client SetSelfSigned(bool selfSigned)
@@ -158,19 +156,23 @@ namespace {{ spec.title | caseUcfirst }}
158
156
{
159
157
if (parameter.Key == "file")
160
158
{
161
- form.Add(((MultipartFormDataContent)parameters["file"]).First()!);
159
+ var fileContent = parameters["file"] as MultipartFormDataContent;
160
+ if (fileContent != null)
161
+ {
162
+ form.Add(fileContent.First()!);
163
+ }
162
164
}
163
165
else if (parameter.Value is IEnumerable<object > enumerable)
164
166
{
165
167
var list = new List<object >(enumerable);
166
168
for (int index = 0; index < list.Count; index++)
167
169
{
168
- form.Add(new StringContent(list[index].ToString()! ), $"{parameter.Key}[{index}]");
170
+ form.Add(new StringContent(list[index]? .ToString() ?? string.Empty ), $"{parameter.Key}[{index}]");
169
171
}
170
172
}
171
173
else
172
174
{
173
- form.Add(new StringContent(parameter.Value.ToString()! ), parameter.Key);
175
+ form.Add(new StringContent(parameter.Value? .ToString() ?? string.Empty ), parameter.Key);
174
176
}
175
177
}
176
178
request.Content = form;
@@ -243,16 +245,27 @@ namespace {{ spec.title | caseUcfirst }}
243
245
}
244
246
245
247
if (contentType.Contains("application/json")) {
246
- message = JObject.Parse(text)["message"]!.ToString();
247
- type = JObject.Parse(text)["type"]?.ToString() ?? string.Empty;
248
+ try
249
+ {
250
+ using var errorDoc = JsonDocument.Parse(text);
251
+ message = errorDoc.RootElement.GetProperty("message").GetString() ?? "";
252
+ if (errorDoc.RootElement.TryGetProperty("type", out var typeElement))
253
+ {
254
+ type = typeElement.GetString() ?? "";
255
+ }
256
+ }
257
+ catch
258
+ {
259
+ message = text;
260
+ }
248
261
} else {
249
262
message = text;
250
263
}
251
264
252
265
throw new {{spec .title | caseUcfirst }}Exception(message, code, type, text);
253
266
}
254
267
255
- return response.Headers.Location.OriginalString;
268
+ return response.Headers.Location? .OriginalString ?? string.Empty ;
256
269
}
257
270
258
271
public Task<Dictionary <string , object ?>> Call(
@@ -298,8 +311,19 @@ namespace {{ spec.title | caseUcfirst }}
298
311
var type = "";
299
312
300
313
if (isJson) {
301
- message = JObject.Parse(text)["message"]!.ToString();
302
- type = JObject.Parse(text)["type"]?.ToString() ?? string.Empty;
314
+ try
315
+ {
316
+ using var errorDoc = JsonDocument.Parse(text);
317
+ message = errorDoc.RootElement.GetProperty("message").GetString() ?? "";
318
+ if (errorDoc.RootElement.TryGetProperty("type", out var typeElement))
319
+ {
320
+ type = typeElement.GetString() ?? "";
321
+ }
322
+ }
323
+ catch
324
+ {
325
+ message = text;
326
+ }
303
327
} else {
304
328
message = text;
305
329
}
@@ -311,13 +335,13 @@ namespace {{ spec.title | caseUcfirst }}
311
335
{
312
336
var responseString = await response.Content.ReadAsStringAsync();
313
337
314
- var dict = JsonConvert.DeserializeObject <Dictionary <string , object >>(
338
+ var dict = JsonSerializer.Deserialize <Dictionary <string , object >>(
315
339
responseString,
316
- DeserializerSettings );
340
+ DeserializerOptions );
317
341
318
- if (convert != null)
342
+ if (convert != null && dict != null )
319
343
{
320
- return convert(dict! );
344
+ return convert(dict);
321
345
}
322
346
323
347
return (dict as T)!;
@@ -337,7 +361,16 @@ namespace {{ spec.title | caseUcfirst }}
337
361
string? idParamName = null,
338
362
Action<UploadProgress >? onProgress = null) where T : class
339
363
{
364
+ if (string.IsNullOrEmpty(paramName))
365
+ throw new ArgumentException("Parameter name cannot be null or empty", nameof(paramName));
366
+
367
+ if (!parameters.ContainsKey(paramName))
368
+ throw new ArgumentException($"Parameter {paramName} not found", nameof(paramName));
369
+
340
370
var input = parameters[paramName] as InputFile;
371
+ if (input == null)
372
+ throw new ArgumentException($"Parameter {paramName} must be an InputFile", nameof(paramName));
373
+
341
374
var size = 0L;
342
375
switch(input.SourceType)
343
376
{
@@ -347,10 +380,16 @@ namespace {{ spec.title | caseUcfirst }}
347
380
size = info.Length;
348
381
break;
349
382
case "stream":
350
- size = (input.Data as Stream).Length;
383
+ var stream = input.Data as Stream;
384
+ if (stream == null)
385
+ throw new InvalidOperationException("Stream data is null");
386
+ size = stream.Length;
351
387
break;
352
388
case "bytes":
353
- size = ((byte[])input.Data).Length;
389
+ var bytes = input.Data as byte[];
390
+ if (bytes == null)
391
+ throw new InvalidOperationException("Byte array data is null");
392
+ size = bytes.Length;
354
393
break;
355
394
};
356
395
@@ -364,10 +403,16 @@ namespace {{ spec.title | caseUcfirst }}
364
403
{
365
404
case "path":
366
405
case "stream":
367
- await (input.Data as Stream).ReadAsync(buffer, 0, (int)size);
406
+ var dataStream = input.Data as Stream;
407
+ if (dataStream == null)
408
+ throw new InvalidOperationException("Stream data is null");
409
+ await dataStream.ReadAsync(buffer, 0, (int)size);
368
410
break;
369
411
case "bytes":
370
- buffer = (byte[])input.Data;
412
+ var dataBytes = input.Data as byte[];
413
+ if (dataBytes == null)
414
+ throw new InvalidOperationException("Byte array data is null");
415
+ buffer = dataBytes;
371
416
break;
372
417
}
373
418
@@ -393,14 +438,16 @@ namespace {{ spec.title | caseUcfirst }}
393
438
// Make a request to check if a file already exists
394
439
var current = await Call<Dictionary <string , object ?>>(
395
440
method: "GET",
396
- path: $"{path}/{parameters[idParamName]}",
441
+ path: $"{path}/{parameters[idParamName! ]}",
397
442
new Dictionary<string , string > { { "content-type", "application/json" } },
398
443
parameters: new Dictionary<string , object ?>()
399
444
);
400
- var chunksUploaded = (long)current["chunksUploaded"];
401
- offset = chunksUploaded * ChunkSize;
445
+ if (current.TryGetValue("chunksUploaded", out var chunksUploadedValue) && chunksUploadedValue != null)
446
+ {
447
+ offset = Convert.ToInt64(chunksUploadedValue) * ChunkSize;
448
+ }
402
449
}
403
- catch (Exception ex)
450
+ catch
404
451
{
405
452
// ignored as it mostly means file not found
406
453
}
@@ -413,6 +460,8 @@ namespace {{ spec.title | caseUcfirst }}
413
460
case "path":
414
461
case "stream":
415
462
var stream = input.Data as Stream;
463
+ if (stream == null)
464
+ throw new InvalidOperationException("Stream data is null");
416
465
stream.Seek(offset, SeekOrigin.Begin);
417
466
await stream.ReadAsync(buffer, 0, ChunkSize);
418
467
break;
@@ -445,12 +494,12 @@ namespace {{ spec.title | caseUcfirst }}
445
494
var id = result.ContainsKey("$id")
446
495
? result["$id"]?.ToString() ?? string.Empty
447
496
: string.Empty;
448
- var chunksTotal = result.ContainsKey ("chunksTotal")
449
- ? (long)result["chunksTotal"]
450
- : 0 ;
451
- var chunksUploaded = result.ContainsKey ("chunksUploaded")
452
- ? (long)result["chunksUploaded"]
453
- : 0 ;
497
+ var chunksTotal = result.TryGetValue ("chunksTotal", out var chunksTotalValue) && chunksTotalValue != null
498
+ ? Convert.ToInt64(chunksTotalValue)
499
+ : 0L ;
500
+ var chunksUploaded = result.TryGetValue ("chunksUploaded", out var chunksUploadedValue) && chunksUploadedValue != null
501
+ ? Convert.ToInt64(chunksUploadedValue)
502
+ : 0L ;
454
503
455
504
headers["x-appwrite-id"] = id;
456
505
@@ -463,7 +512,11 @@ namespace {{ spec.title | caseUcfirst }}
463
512
chunksUploaded: chunksUploaded));
464
513
}
465
514
466
- return converter(result);
515
+ // Convert to non-nullable dictionary for converter
516
+ var nonNullableResult = result.Where(kvp => kvp.Value != null)
517
+ .ToDictionary(kvp => kvp.Key, kvp => kvp.Value!);
518
+
519
+ return converter(nonNullableResult);
467
520
}
468
521
}
469
522
}
0 commit comments