Skip to content

Commit

Permalink
fix: GoFeatureFlagUser class was not serialized. (open-feature#33)
Browse files Browse the repository at this point in the history
* fix:  GoFeatureFlagUser class was not serialized.

System.Text.Json does not serialize private members of a class.
Since the class `GoFeatureFlagUser` had the following private members:
```
        private string Key { get; set; }
        private bool Anonymous { get; set; }
        private Dictionary<string, object> Custom { get; set; }
```
When it was serialized as the User in GOFeatureFlagRequest,
the Json that was returned was `{ "user": {},  ...`
instead of `{ "user": { "key: :  ...`

This commit fixes this issue by making the property public
and adding a test.

* updates documents
The name of the package was wrong it should be
***OpenFeature.Contrib.GOFeatureFlag*** and
not *OpenFeature.Contrib.Providers.GOFeatureFlag*

Signed-off-by: Eric Holton <[email protected]>

* chore: fix white space

Signed-off-by: Eric Holton <[email protected]>

* chore: fix white space

Signed-off-by: Eric Holton <[email protected]>

---------

Signed-off-by: Eric Holton <[email protected]>
  • Loading branch information
mrjavaguy authored Feb 3, 2023
1 parent 370ea41 commit 0f222b4
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,9 @@ public override async Task<ResolutionDetails<Value>> ResolveStructureValue(strin
private async Task<GoFeatureFlagResponse> CallApi<T>(string flagKey, T defaultValue,
EvaluationContext context = null)
{
var user = GoFeatureFlagUser.FromEvaluationContext(context);
var request = new GOFeatureFlagRequest<T>
{
User = user,
User = context,
DefaultValue = defaultValue
};
var goffRequest = JsonSerializer.Serialize(request, _serializerOptions);
Expand Down
115 changes: 64 additions & 51 deletions src/OpenFeature.Contrib.Providers.GOFeatureFlag/GoFeatureFlagUser.cs
Original file line number Diff line number Diff line change
@@ -1,52 +1,65 @@
using System.Collections.Generic;
using System.Linq;
using OpenFeature.Contrib.Providers.GOFeatureFlag.exception;
using OpenFeature.Model;

namespace OpenFeature.Contrib.Providers.GOFeatureFlag
{
/// <summary>
/// GOFeatureFlagUser is the representation of a User inside GO Feature Flag.
/// </summary>
public class GoFeatureFlagUser
{
private const string AnonymousField = "anonymous";
private const string KeyField = "targetingKey";
private string Key { get; set; }
private bool Anonymous { get; set; }
private Dictionary<string, object> Custom { get; set; }

/**
* FromEvaluationContext convert the evaluation context into a GOFeatureFlagUser Object.
*/
public static GoFeatureFlagUser FromEvaluationContext(EvaluationContext ctx)
{
try
{
if (ctx is null)
throw new InvalidEvaluationContext("GO Feature Flag need an Evaluation context to work.");
if (!ctx.GetValue(KeyField).IsString)
throw new InvalidTargetingKey("targetingKey field MUST be a string.");
}
catch (KeyNotFoundException e)
{
throw new InvalidTargetingKey("targetingKey field is mandatory.", e);
}

var anonymous = ctx.ContainsKey(AnonymousField) && ctx.GetValue(AnonymousField).IsBoolean
? ctx.GetValue(AnonymousField).AsBoolean
: false;

var custom = ctx.AsDictionary().ToDictionary(x => x.Key, x => x.Value.AsObject);
custom.Remove(AnonymousField);
custom.Remove(KeyField);

return new GoFeatureFlagUser
{
Key = ctx.GetValue("targetingKey").AsString,
Anonymous = anonymous.Value,
Custom = custom
};
}
}
using System.Collections.Generic;
using System.Linq;

using OpenFeature.Contrib.Providers.GOFeatureFlag.exception;
using OpenFeature.Model;

namespace OpenFeature.Contrib.Providers.GOFeatureFlag
{
/// <summary>
/// GOFeatureFlagUser is the representation of a User inside GO Feature Flag.
/// </summary>
public class GoFeatureFlagUser
{
private const string AnonymousField = "anonymous";
private const string KeyField = "targetingKey";

/// <summary>
/// The targeting key for the user.
/// </summary>
public string Key { get; private set; }

/// <summary>
/// Is the user Anonymous.
/// </summary>
public bool Anonymous { get; private set; }

/// <summary>
/// Additional Custom Data to pass to GO Feature Flag.
/// </summary>
public Dictionary<string, object> Custom { get; private set; }

/**
* Convert the evaluation context into a GOFeatureFlagUser Object.
*/
public static implicit operator GoFeatureFlagUser(EvaluationContext ctx)
{
try
{
if (ctx is null)
throw new InvalidEvaluationContext("GO Feature Flag need an Evaluation context to work.");
if (!ctx.GetValue(KeyField).IsString)
throw new InvalidTargetingKey("targetingKey field MUST be a string.");
}
catch (KeyNotFoundException e)
{
throw new InvalidTargetingKey("targetingKey field is mandatory.", e);
}

var anonymous = ctx.ContainsKey(AnonymousField) && ctx.GetValue(AnonymousField).IsBoolean
? ctx.GetValue(AnonymousField).AsBoolean
: false;

var custom = ctx.AsDictionary().ToDictionary(x => x.Key, x => x.Value.AsObject);
custom.Remove(AnonymousField);
custom.Remove(KeyField);

return new GoFeatureFlagUser
{
Key = ctx.GetValue("targetingKey").AsString,
Anonymous = anonymous.Value,
Custom = custom
};
}
}
}
16 changes: 8 additions & 8 deletions src/OpenFeature.Contrib.Providers.GOFeatureFlag/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,32 @@ The first things we will do is install the **Open Feature SDK** and the **GO Fea

### .NET Cli
```shell
dotnet add package OpenFeature.Contrib.Providers.GOFeatureFlag
dotnet add package OpenFeature.Contrib.GOFeatureFlag
```
### Package Manager

```shell
NuGet\Install-Package OpenFeature.Contrib.Providers.GOFeatureFlag
NuGet\Install-Package OpenFeature.Contrib.GOFeatureFlag
```
### Package Reference

```xml
<PackageReference Include="OpenFeature.Contrib.Providers.GOFeatureFlag" />
<PackageReference Include="OpenFeature.Contrib.GOFeatureFlag" />
```
### Packet cli

```shell
paket add OpenFeature.Contrib.Providers.GOFeatureFlag
paket add OpenFeature.Contrib.GOFeatureFlag
```

### Cake

```shell
// Install OpenFeature.Contrib.Providers.GOFeatureFlag as a Cake Addin
#addin nuget:?package=OpenFeature.Contrib.Providers.GOFeatureFlag
// Install OpenFeature.Contrib.GOFeatureFlag as a Cake Addin
#addin nuget:?package=OpenFeature.Contrib.GOFeatureFlag

// Install OpenFeature.Contrib.Providers.GOFeatureFlag as a Cake Tool
#tool nuget:?package=OpenFeature.Contrib.Providers.GOFeatureFlag
// Install OpenFeature.Contrib.GOFeatureFlag as a Cake Tool
#tool nuget:?package=OpenFeature.Contrib.GOFeatureFlag
```

## Initialize your Open Feature client
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Text.Json;

using OpenFeature.Model;

using Xunit;

namespace OpenFeature.Contrib.Providers.GOFeatureFlag.Test;

public class GoFeatureFlagUserTest
{
[Fact]
public void GoFeatureFlagUserSerializesCorrectly()
{
var userContext = EvaluationContext.Builder()
.Set("targetingKey", "1d1b9238-2591-4a47-94cf-d2bc080892f1")
.Set("firstname", "john")
.Set("lastname", "doe")
.Set("email", "[email protected]")
.Set("admin", true)
.Set("anonymous", false)
.Build();

GoFeatureFlagUser user = userContext;

var userAsString = JsonSerializer.Serialize(user, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

Assert.Contains("{\"key\":\"1d1b9238-2591-4a47-94cf-d2bc080892f1\",\"anonymous\":false,\"custom\":{", userAsString);
}
}

0 comments on commit 0f222b4

Please sign in to comment.