Skip to content

Commit 2185653

Browse files
committed
Refactor to explicit serializer
- Global one can be affected by global settings that can mess things up - Don't mess with external code when we add contracts/custom serializers etc
1 parent 151e82b commit 2185653

File tree

4 files changed

+50
-16
lines changed

4 files changed

+50
-16
lines changed

metabase-exporter/ApiObjects.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class Card
2323
public ResultMetadata[] ResultMetadata { get; set; }
2424

2525
[JsonProperty("metadata_checksum")]
26-
public string MetadataChecksum => GeneralExtensions.MD5Base64(JsonConvert.SerializeObject(ResultMetadata));
26+
public string MetadataChecksum => GeneralExtensions.MD5Base64(Program.Serializer.SerializeObject(ResultMetadata));
2727

2828
[JsonProperty("database_id")]
2929
public DatabaseId DatabaseId { get; set; }

metabase-exporter/GeneralExtensions.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Linq;
45
using System.Text;
56
using System.Threading.Tasks;
7+
using Newtonsoft.Json;
68

79
namespace metabase_exporter;
810

@@ -40,8 +42,10 @@ public static async Task<IReadOnlyList<TResult>> Sequence<TResult>(this IEnumera
4042

4143
public static string MD5Base64(string x)
4244
{
43-
var md5Value = System.Security.Cryptography.MD5.HashData(Encoding.UTF8.GetBytes(x));
44-
return Convert.ToBase64String(md5Value);
45+
using (var md5 = System.Security.Cryptography.MD5.Create()) {
46+
byte[] md5Value = md5.ComputeHash(Encoding.UTF8.GetBytes(x));
47+
return Convert.ToBase64String(md5Value);
48+
}
4549
}
4650

4751
public static TValue GetOrThrow<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dict, TKey key, string error)
@@ -53,4 +57,19 @@ public static TValue GetOrThrow<TKey, TValue>(this IReadOnlyDictionary<TKey, TVa
5357
throw new KeyNotFoundException($"Key not found: {key}\n{error}");
5458
}
5559

60+
public static T DeserializeObject<T>(this JsonSerializer serializer, string rawJson)
61+
{
62+
using var reader = new StringReader(rawJson);
63+
using var jsonReader = new JsonTextReader(reader);
64+
return serializer.Deserialize<T>(jsonReader);
65+
}
66+
67+
public static string SerializeObject<T>(this JsonSerializer serializer, T obj)
68+
{
69+
using var writer = new StringWriter();
70+
using var jsonWriter = new JsonTextWriter(writer);
71+
serializer.Serialize(jsonWriter, obj);
72+
return writer.ToString();
73+
}
74+
5675
}

metabase-exporter/MetabaseApi.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ HttpRequestMessage request() =>
3232
var response = await sessionManager.Send(request);
3333
try
3434
{
35-
return JsonConvert.DeserializeObject<Card>(response);
35+
return Program.Serializer.DeserializeObject<Card>(response);
3636
}
3737
catch (JsonSerializationException e)
3838
{
@@ -67,7 +67,7 @@ HttpRequestMessage request() =>
6767
var response = await sessionManager.Send(request);
6868
try
6969
{
70-
return JsonConvert.DeserializeObject<Dashboard>(response);
70+
return Program.Serializer.DeserializeObject<Dashboard>(response);
7171
}
7272
catch (JsonSerializationException e)
7373
{
@@ -141,7 +141,7 @@ HttpRequestMessage request1() =>
141141
var response = await sessionManager.Send(request1);
142142
try
143143
{
144-
return JsonConvert.DeserializeObject<DashboardCard>(response);
144+
return Program.Serializer.DeserializeObject<DashboardCard>(response);
145145
}
146146
catch (JsonSerializationException e)
147147
{
@@ -159,7 +159,7 @@ HttpRequestMessage request() =>
159159
var response = await sessionManager.Send(request);
160160
try
161161
{
162-
return JsonConvert.DeserializeObject<Collection>(response);
162+
return Program.Serializer.DeserializeObject<Collection>(response);
163163
}
164164
catch (JsonSerializationException e)
165165
{
@@ -169,7 +169,7 @@ HttpRequestMessage request() =>
169169

170170
static (StringContent HttpContent, string Json) ToJsonContent(object o)
171171
{
172-
var json = JsonConvert.SerializeObject(o);
172+
var json = Program.Serializer.SerializeObject(o);
173173
var content = new StringContent(json, Encoding.UTF8, "application/json");
174174
return (content, json);
175175
}
@@ -191,7 +191,7 @@ public async Task<IReadOnlyList<Card>> GetAllCards()
191191
HttpRequestMessage request() => new HttpRequestMessage(HttpMethod.Get, new Uri("/api/card", UriKind.Relative));
192192
var response = await sessionManager.Send(request);
193193
try {
194-
return JsonConvert.DeserializeObject<Card[]>(response);
194+
return Program.Serializer.DeserializeObject<Card[]>(response);
195195
} catch (JsonReaderException e) {
196196
throw new MetabaseApiException($"Error parsing response for {nameof(Card)} from:\n{response}", e);
197197
}
@@ -204,7 +204,7 @@ public async Task<IReadOnlyList<Collection>> GetAllCollections()
204204
response = response.Replace("\"id\":\"root\"", "\"id\":\"0\"");
205205
try
206206
{
207-
return JsonConvert.DeserializeObject<Collection[]>(response);
207+
return Program.Serializer.DeserializeObject<Collection[]>(response);
208208
}
209209
catch (JsonSerializationException e)
210210
{
@@ -217,7 +217,7 @@ public async Task<IReadOnlyList<Dashboard>> GetAllDashboards()
217217
HttpRequestMessage request() => new HttpRequestMessage(HttpMethod.Get, new Uri("/api/dashboard", UriKind.Relative));
218218
var response = await sessionManager.Send(request);
219219
try {
220-
var dashboards = JsonConvert.DeserializeObject<Dashboard[]>(response);
220+
var dashboards = Program.Serializer.DeserializeObject<Dashboard[]>(response);
221221
// the endpoint that returns all dashboards does not include all detail for each dashboard
222222
return await dashboards.Traverse(async dashboard => await GetDashboard(dashboard.Id));
223223
}
@@ -233,7 +233,7 @@ public async Task<Dashboard> GetDashboard(DashboardId dashboardId)
233233
var response = await sessionManager.Send(request);
234234
try
235235
{
236-
return JsonConvert.DeserializeObject<Dashboard>(response);
236+
return Program.Serializer.DeserializeObject<Dashboard>(response);
237237
}
238238
catch (JsonSerializationException e)
239239
{
@@ -247,7 +247,7 @@ public async Task<IReadOnlyList<DatabaseId>> GetAllDatabaseIds()
247247
var response = await sessionManager.Send(request);
248248
try
249249
{
250-
var databases = JsonConvert.DeserializeObject<JObject>(response)["data"];
250+
var databases = Program.Serializer.DeserializeObject<JObject>(response)["data"];
251251
return databases.Select(d => new DatabaseId((int) d["id"])).ToImmutableList();
252252
}
253253
catch (JsonSerializationException e)
@@ -262,7 +262,7 @@ public async Task<RunCardResult> RunCard(CardId card)
262262
var response = await sessionManager.Send(request);
263263
try
264264
{
265-
return JsonConvert.DeserializeObject<RunCardResult>(response);
265+
return Program.Serializer.DeserializeObject<RunCardResult>(response);
266266
}
267267
catch (JsonSerializationException e)
268268
{

metabase-exporter/Program.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,40 @@ public static async Task Main(string[] args)
2424

2525
var rawConfig = builder.Build();
2626
var config = ParseConfig(rawConfig);
27+
28+
_serializer = JsonSerializer.Create(new JsonSerializerSettings
29+
{
30+
//Formatting = Formatting.Indented // don't set this, it will mess checksums
31+
});
32+
_indentedSerializer = JsonSerializer.Create(new JsonSerializerSettings
33+
{
34+
Formatting = Formatting.Indented,
35+
});
36+
2737
var api = await InitApi(config.MetabaseApiSettings);
2838
await config.Switch(
2939
export: api.Export,
3040
import: api.Import,
3141
testQuestions: _ => api.TestQuestions());
3242
}
3343

44+
static JsonSerializer _serializer;
45+
public static JsonSerializer Serializer => _serializer;
46+
47+
static JsonSerializer _indentedSerializer;
48+
3449
static async Task Export(this MetabaseApi api, Config.Export export)
3550
{
3651
var state = await api.Export(export.ExcludePersonalCollections);
37-
var stateJson = JsonConvert.SerializeObject(state, Formatting.Indented);
52+
var stateJson = _indentedSerializer.SerializeObject(state);
3853
File.WriteAllText(path: export.OutputFilename, contents: stateJson);
3954
Console.WriteLine($"Exported current state for {export.MetabaseApiSettings.MetabaseApiUrl} to {export.OutputFilename}");
4055
}
4156

4257
static async Task Import(this MetabaseApi api, Config.Import import)
4358
{
4459
var rawState = File.ReadAllText(import.InputFilename);
45-
var state = JsonConvert.DeserializeObject<MetabaseState>(rawState);
60+
var state = Program.Serializer.DeserializeObject<MetabaseState>(rawState);
4661
await api.Import(state, import.DatabaseMapping, import.IgnoredDatabases);
4762
Console.WriteLine($"Done importing from {import.InputFilename} into {import.MetabaseApiSettings.MetabaseApiUrl}");
4863
}

0 commit comments

Comments
 (0)