Skip to content

Commit

Permalink
Updates to working with json (#15)
Browse files Browse the repository at this point in the history
* Updates to working with json

* Add FromJsonExtension
  • Loading branch information
YuriyDurov authored Jan 5, 2024
1 parent 6526a71 commit a64aca3
Show file tree
Hide file tree
Showing 18 changed files with 299 additions and 113 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace BitzArt.Flux;

internal class FluxJsonDeserializationException<TModel> : Exception
{
public FluxJsonDeserializationException()
: base($"Failed to deserialize JSON to {typeof(TModel).Name}")
{ }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace BitzArt.Flux;

internal class FluxJsonFileReadException : Exception
{
public FluxJsonFileReadException(string path, Exception innerException)
: base($"Error reading JSON from file '{path}'. See inner exception for details", innerException)
{ }
}
54 changes: 2 additions & 52 deletions src/BitzArt.Flux.Json/Builder/Extensions/AddSetExtension.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;

namespace BitzArt.Flux;

public static class AddSetExtension
{
public static IFluxJsonSetBuilder<TModel> AddSet<TModel>(this IFluxJsonServiceBuilder serviceBuilder,
string filePath, string? name = null)
string? name = null)
where TModel : class
{
var builder = new FluxJsonSetBuilder<TModel>(serviceBuilder);

var services = serviceBuilder.Services;
var serviceFactory = builder.ServiceFactory;

var path = GetFilePath(filePath, serviceBuilder.BasePath);
builder.SetOptions.Items = TryGetItemsFromJsonFile<TModel>(path, serviceBuilder.ServiceOptions.SerializerOptions);

serviceFactory.AddSet<TModel>(builder.SetOptions, name);

services.AddScoped(x =>
Expand All @@ -29,17 +25,14 @@ public static IFluxJsonSetBuilder<TModel> AddSet<TModel>(this IFluxJsonServiceBu
}

public static IFluxJsonSetBuilder<TModel, TKey> AddSet<TModel, TKey>(this IFluxJsonServiceBuilder serviceBuilder,
string filePath, string? name = null)
string? name = null)
where TModel : class
{
var builder = new FluxJsonSetBuilder<TModel, TKey>(serviceBuilder);

var services = serviceBuilder.Services;
var serviceFactory = serviceBuilder.ServiceFactory;

var path = GetFilePath(filePath, serviceBuilder.BasePath);
builder.SetOptions.Items = TryGetItemsFromJsonFile<TModel>(path, serviceBuilder.ServiceOptions.SerializerOptions);

serviceFactory.AddSet<TModel, TKey>(builder.SetOptions, name);

services.AddScoped(x =>
Expand All @@ -56,47 +49,4 @@ public static IFluxJsonSetBuilder<TModel, TKey> AddSet<TModel, TKey>(this IFluxJ

return builder;
}

private static ICollection<TModel> TryGetItemsFromJsonFile<TModel>(string path, JsonSerializerOptions options)
{
try
{
return GetItemsFromJsonFile<TModel>(path, options);
}
catch (Exception ex)
{
throw new FluxJsonFileReadException(path, ex);
}
}

private static ICollection<TModel> GetItemsFromJsonFile<TModel>(string path, JsonSerializerOptions options)
{
var jsonString = File.ReadAllText(path);
var items = JsonSerializer.Deserialize<List<TModel>>(jsonString, options);

if (items is null) throw new FluxJsonDeserializationException<List<TModel>>();

return items;
}

private static string GetFilePath(string filePath, string? basePath = null)
{
if (basePath is not null) filePath = Path.Combine(basePath, filePath);

return filePath;
}
}

internal class FluxJsonFileReadException : Exception
{
public FluxJsonFileReadException(string path, Exception innerException)
: base($"Error reading JSON from file '{path}'. See inner exception for details", innerException)
{ }
}

internal class FluxJsonDeserializationException<TModel> : Exception
{
public FluxJsonDeserializationException()
: base($"Failed to deserialize JSON to {typeof(TModel).Name}")
{ }
}
13 changes: 13 additions & 0 deletions src/BitzArt.Flux.Json/Builder/Extensions/ConfigureJsonExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Text.Json;

namespace BitzArt.Flux;

public static class ConfigureJsonExtension
{
public static IFluxJsonServiceBuilder ConfigureJson(this IFluxJsonServiceBuilder builder, Action<JsonSerializerOptions> configure)
{
configure(builder.ServiceOptions.SerializerOptions);

return builder;
}
}
28 changes: 28 additions & 0 deletions src/BitzArt.Flux.Json/Builder/Extensions/FromJsonExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Text.Json;

namespace BitzArt.Flux;

public static class FromJsonExtension
{
public static IFluxJsonSetBuilder<TModel> FromJson<TModel>(this IFluxJsonSetBuilder<TModel> builder,
string json)
where TModel : class
{
builder.SetOptions.Items =
JsonSerializer.Deserialize<List<TModel>>(json, builder.ServiceOptions.SerializerOptions)
?? throw new FluxJsonDeserializationException<List<TModel>>();

return builder;
}

public static IFluxJsonSetBuilder<TModel, TKey> FromJson<TModel, TKey>(this IFluxJsonSetBuilder<TModel, TKey> builder,
string json)
where TModel : class
{
builder.SetOptions.Items =
JsonSerializer.Deserialize<List<TModel>>(json, builder.ServiceOptions.SerializerOptions)
?? throw new FluxJsonDeserializationException<List<TModel>>();

return builder;
}
}
54 changes: 54 additions & 0 deletions src/BitzArt.Flux.Json/Builder/Extensions/FromJsonFileExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Text.Json;

namespace BitzArt.Flux;

public static class FromJsonFileExtension
{
public static IFluxJsonSetBuilder<TModel> FromJsonFile<TModel>(this IFluxJsonSetBuilder<TModel> builder,
string filePath)
where TModel : class
{
var path = GetFilePath(filePath, builder.ServiceOptions.BaseFilePath);
builder.SetOptions.Items = TryGetItemsFromJsonFile<TModel>(path, builder.ServiceOptions.SerializerOptions);

return builder;
}

public static IFluxJsonSetBuilder<TModel, TKey> FromJsonFile<TModel, TKey>(this IFluxJsonSetBuilder<TModel, TKey> builder,
string filePath)
where TModel : class
{
var path = GetFilePath(filePath, builder.ServiceOptions.BaseFilePath);
builder.SetOptions.Items = TryGetItemsFromJsonFile<TModel>(path, builder.ServiceOptions.SerializerOptions);

return builder;
}

private static ICollection<TModel> TryGetItemsFromJsonFile<TModel>(string path, JsonSerializerOptions options)
{
try
{
return GetItemsFromJsonFile<TModel>(path, options);
}
catch (Exception ex)
{
throw new FluxJsonFileReadException(path, ex);
}
}

private static ICollection<TModel> GetItemsFromJsonFile<TModel>(string path, JsonSerializerOptions options)
{
var jsonString = File.ReadAllText(path);
var items = JsonSerializer.Deserialize<List<TModel>>(jsonString, options)
?? throw new FluxJsonDeserializationException<List<TModel>>();

return items;
}

private static string GetFilePath(string filePath, string? basePath = null)
{
if (basePath is not null) filePath = Path.Combine(basePath, filePath);

return filePath;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ namespace BitzArt.Flux;

public static class UsingJsonExtension
{
public static IFluxJsonServiceBuilder UsingJson(this IFluxServicePreBuilder prebuilder, string? basePath = null,
Action<JsonSerializerOptions>? configure = null)
public static IFluxJsonServiceBuilder UsingJson(this IFluxServicePreBuilder prebuilder)
{
prebuilder.Services.AddLogging();

var builder = new FluxJsonServiceBuilder(prebuilder, basePath);
var builder = new FluxJsonServiceBuilder(prebuilder);

var fluxServiceProvider = builder.ServiceFactory;
builder.Factory.ServiceContexts.Add(fluxServiceProvider);
Expand All @@ -20,8 +19,6 @@ public static IFluxJsonServiceBuilder UsingJson(this IFluxServicePreBuilder preb
return new FluxServiceContext(fluxServiceProvider, x);
});

configure?.Invoke(builder.ServiceOptions.SerializerOptions);

return builder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace BitzArt.Flux;

public static class WithBaseFilePathExtension
{
public static IFluxJsonServiceBuilder WithBaseFilePath(this IFluxJsonServiceBuilder builder, string baseFilePath)
{
builder.ServiceOptions.BaseFilePath = baseFilePath;

return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ namespace BitzArt.Flux;
public interface IFluxJsonServiceBuilder : IFluxServiceBuilder
{
public FluxJsonServiceOptions ServiceOptions { get; }
internal string? BasePath { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ internal class FluxJsonServiceBuilder : IFluxJsonServiceBuilder
public IFluxServiceFactory ServiceFactory { get; set; }
public IFluxFactory Factory { get; init; }
public FluxJsonServiceOptions ServiceOptions { get; init; }
public string? BasePath { get; }

public FluxJsonServiceBuilder(IFluxServicePreBuilder prebuilder, string? basePath = null)
public FluxJsonServiceBuilder(IFluxServicePreBuilder prebuilder)
{
Services = prebuilder.Services;
Factory = prebuilder.Factory;
ServiceOptions = new FluxJsonServiceOptions();
BasePath = basePath;

if (prebuilder.Name is null) throw new Exception("Missing Name in Flux Service configuration. Consider using .WithName() when configuring external services.");
if (prebuilder.Name is null) throw new Exception("Missing Name in Flux Service configuration. Specify service names when configuring external services.");

ServiceFactory = new FluxJsonServiceFactory(ServiceOptions, prebuilder.Name);
}
Expand Down
2 changes: 1 addition & 1 deletion src/BitzArt.Flux.Json/Builder/Models/FluxJsonSetBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal class FluxJsonSetBuilder<TModel> : IFluxJsonSetBuilder<TModel>
public IFluxServiceFactory ServiceFactory => ServiceBuilder.ServiceFactory;
public IFluxFactory Factory => ServiceBuilder.Factory;
public FluxJsonServiceOptions ServiceOptions => ServiceBuilder.ServiceOptions;
public string? BasePath => ServiceBuilder.BasePath;
public string? BaseFilePath => ServiceBuilder.ServiceOptions.BaseFilePath;

public FluxJsonSetOptions<TModel> SetOptions { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ namespace BitzArt.Flux;
public class FluxJsonServiceOptions
{
public JsonSerializerOptions SerializerOptions { get; set; } = new();
public string? BaseFilePath { get; set; }
}
8 changes: 2 additions & 6 deletions src/BitzArt.Flux.Json/Context/Models/FluxJsonSetContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,8 @@ public virtual Task<TModel> GetAsync(object? id, params object[]? parameters)

var itemId = SetOptions.KeyPropertyExpression.Compile().Invoke(item);
return Equals(itemId, id);
});
}) ?? throw new FluxItemNotFoundException<TModel>(id);

if (existingItem is null) throw new FluxItemNotFoundException<TModel>(id);

return Task.FromResult(existingItem);
}
}
Expand Down Expand Up @@ -87,9 +85,7 @@ public Task<TModel> GetAsync(TKey? id, params object[]? parameters)

var itemId = SetOptions.KeyPropertyExpression.Compile().Invoke(item);
return Equals(itemId, id);
});

if (existingItem is null) throw new FluxItemNotFoundException<TModel>(id);
}) ?? throw new FluxItemNotFoundException<TModel>(id);

return Task.FromResult(existingItem);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public FluxRestServiceBuilder(IFluxServicePreBuilder prebuilder, string? baseUrl
ServiceOptions = new(baseUrl);
HttpClientConfiguration = null;

if (prebuilder.Name is null) throw new Exception("Missing Name in Flux Service configuration. Consider using .WithName() when configuring external services.");
if (prebuilder.Name is null) throw new Exception("Missing Name in Flux Service configuration. Specify service names when configuring external services.");
ServiceFactory = new FluxRestServiceFactory(ServiceOptions, prebuilder.Name);
}
}
Loading

0 comments on commit a64aca3

Please sign in to comment.