Konvertere HAL+JSON
Et eksempel på hvordan man kan lage en tilpasset HAL+JSON konverterer for å serialisere og deserialisere lister av rettigheter med System.Text.Json.
Tilpasset HAL+JSON konverterer
(eng: custom HAL+JSON converter)
I denne leksjonen vil vi vise hvordan man lager en tilpasset konverterer for HAL+JSON for System.Text.Json
.
Detaljene vil være sterkt knyttet til System.Text.Json
og vil ikke kunne brukes uten modifikasjoner mot andre JSON biblioteker.
Vi har basert implementasjonen på Microsoft - How to write custom converters for JSON serialization (marshalling) in .NET
og bruker factory pattern.
JsonConverterFactory
public class EmbeddedListConverter : JsonConverterFactory
Tilpassede konverterere som bruker factory mønsteret må implementere to funksjoner:
CanConvert()
som bestemmer om konvertereren støtter denne typen,CreateConverter()
som lager enJsonConverter
som kan håndtere serialisering og deserialisering av denne typen.
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsGenericType)
{
return false;
}
if (typeToConvert.GetGenericTypeDefinition() != typeof(List<>))
{
return false;
}
Type listType = typeToConvert.GetGenericArguments()[0];
if (listType != typeof(Right))
{
return false;
}
return true;
}
Denne implementasjonen av CanConvert()
vil kun akseptere List<Right>
.
Den eneste endringen som må gjøres for å håndtere lister av andre objekter, som for eksempel Roles
, er å legge til en sjekk som aksepterer den her.
Resten av konvertereren trenger ingen endring for å støtte det.
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Type listValueType = typeToConvert.GetGenericArguments()[0];
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(EmbeddedListConverterInner<>).MakeGenericType(
new Type[] { listValueType }),
BindingFlags.Instance | BindingFlags.Public,
binder: null,
args: new object[] { options },
culture: null);
return converter;
}
JsonConverter
Oppgaven som skal utføres av JsonConverter er å konvertere mellom lister av objekter i klientkoden og JSON som aksepteres av Altinn.
I dette eksempelet vil vi benytte modellen for en rettighet Right
.
System.Text.Json
støtter allerede serialisering av objekter hvor alle attributtene har enkle typer (se: JsonSerilizerOptions.GetConverter()
).
Det som gjenstår å beskrive er hvordan lister av disse objektene skal serialiseres (Write()
) og deserialiseres (Read()
).
Eksempel på HAL+JSON
{
"_links": {
...
},
"_embedded": {
"rights": [
{
"RightID": 0,
"RightType": "Service",
"ServiceCode": "1337",
"ServiceEditionCode": 1,
"Action": "Read",
"RightSourceType": "DirectlyDelegatedRights",
"IsDelegatable": true
},
{
"RightID": 1,
...
}
]
}
}
EmbeddedListConverterInner klassen
private class EmbeddedListConverterInner<T> : JsonConverter<List<T>>
{
private readonly JsonConverter<T> _converter;
private readonly Type _type;
public EmbeddedListConverterInner(JsonSerializerOptions options)
{
_converter = (JsonConverter<T>)options.GetConverter(typeof(T));
_type = typeof(T);
}
Read
Read()
må
- lage listen med
Rights
, - kalle konvertereren for
Rights
som ble satt i konstruktøren, - ignorere og gå videre når den kommer til
JsonTokenType.EndObject
, - returnere listen når den kommer til slutten av
array
.
public override List<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var list = new List<T>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
continue;
}
if (reader.TokenType == JsonTokenType.EndArray)
{
return list;
}
T element = _converter.Read(ref reader, _type, options);
list.Add(element);
}
}
Write
Write()
skal kun legge til array
notasjon rundt utlistingen av Rights
.
public override void Write(Utf8JsonWriter writer, List<T> list, JsonSerializerOptions options)
{
writer.WriteStartArray();
foreach (T value in list)
{
_converter.Write(writer, value, options);
}
writer.WriteEndArray();
}
I neste leksjon skal vi bruke HAL+JSON modellene og konvertereren til å håndtere responsen fra GET {who}/authorization/Delegations
.