Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
A partir do .NET 11, JsonSerializer suporta tipos de união C# 15. Um sindicato detém um dos tipos de caso na sua declaração.
JsonSerializer escreve o valor ativo do caso e pode lê-lo novamente.
Serializar e desserializar valores de união
Declare uma união cujos casos têm tipos distintos de tokens JSON:
public union Payload(int, string, Message);
public sealed record Message(string Text);
Use JsonSerializer para serializar e desserializar a união:
Payload payload = new Message("Ready");
string json = JsonSerializer.Serialize(payload);
Payload copy = JsonSerializer.Deserialize<Payload>(json);
O JSON serializado contém o valor do caso ativo, em vez de um invólucro ou discriminador:
{"Text":"Ready"}
Por defeito, o serializador classifica o JSON recebido por tipo de token. Na união anterior, um número JSON seleciona int, uma cadeia JSON seleciona string, e um objeto JSON seleciona Message.
Com JsonSerializerOptions.Web, um(a) int também pode ser lido de uma string JSON. Tanto os casos int como string de Payload assumem então o tipo de token de string. Até "25%" lança JsonException para ambiguidade antes do serializador analisar qualquer um dos casos. Para ler strings com os padrões da web, forneça um classificador personalizado que escolha o caso.
Distinguir casos com o mesmo tipo de token JSON
A classificação de tokens não consegue distinguir dois casos que ambos serializam como objetos JSON. Aplique JsonUnionAttribute e selecione JsonUnionTypeStructuralClassifier para classificar casos de objeto pelos nomes das respetivas propriedades:
[JsonUnion(TypeClassifier = typeof(JsonUnionTypeStructuralClassifier))]
public union Pet(Dog, Cat);
public sealed record Dog(string Name, string Breed);
public sealed record Cat(string Name, int Lives);
Aqui, JsonUnionAttribute seleciona um classificador para a união existente Pet ; aplicá-lo a um tipo comum não transforma esse tipo numa união.
O classificador seleciona Dog quando a carga útil contém Breed e seleciona Cat quando contém Lives:
Pet pet = JsonSerializer.Deserialize<Pet>(
"""{"Name":"Rex","Breed":"Husky"}""");
Para objetos JSON, o classificador estrutural começa com os casos de objetos compatíveis e restringe esses conjuntos à medida que lê os nomes de propriedades ao nível raiz reconhecidos. As propriedades obrigatórias eliminam os casos quando estas estão ausentes. JsonUnmappedMemberHandling.Disallow remove um caso quando a carga útil contém uma propriedade que o caso não declara. A classificação só tem sucesso quando resta um caso.
O classificador estrutural não inspeciona valores de propriedades, objetos aninhados, conteúdos de string ou elementos de array. Tenha estas consequências em mente:
- Uma carga útil que deixa zero ou múltiplos candidatos lança JsonException.
- Os contratos de objetos sobrepostos ou ocultos podem ser rejeitados quando o classificador é criado.
- Múltiplos casos não-objeto que usam o mesmo tipo de token JSON não são suportados. Por exemplo,
Guidestringambos usam strings JSON. - Um caso de objeto simples não pode ser misturado com um dicionário,
JsonObjectou outro caso em forma de objeto que não seja POCO. - Casos de união aninhada e casos polimórficos não são suportados.
- ReferenceHandler.Preserve não é suportado.
- Uma configuração que não consegue distinguir os seus casos lança NotSupportedException quando o serializador constrói o classificador.
Escolha sindicatos ou hierarquias fechadas
Use um sindicato quando precisar de preservar um formato JSON sem discriminadores que não controla, ou quando os casos têm formas JSON distintas. Por exemplo, os casos int e string de Payload podem ser distinguidos pelo tipo de token JSON. Para casos de objetos como Pet(Dog, Cat), no entanto, alterações nos nomes das propriedades podem afetar o caso que um classificador estrutural seleciona.
Quando controla os tipos e o contrato JSON, uma hierarquia fechada com polimorfismo inferido pode, em alternativa, identificar tipos de objeto através de um discriminador:
[JsonPolymorphic(InferClosedTypePolymorphism = true)]
public closed record Event;
public sealed record Created(int Id) : Event;
public sealed record Deleted(int Id) : Event;
JsonSerializer.Serialize<Event>(new Created(42)) escreve {"$type":"Created","Id":42}. Ambos os tipos derivados declaram Id, mas o discriminador identifica o caso independentemente das suas propriedades. Isto torna a seleção de casos mais estável à medida que as propriedades evoluem. Ao contrário dos tipos de união, os tipos derivados têm de partilhar uma classe base, e tem de optar explicitamente pelo polimorfismo inferido; o modificador closed por si só não adiciona um discriminador.
Fornecer um classificador personalizado
Deriva do JsonTypeClassifierFactory momento em que a classificação padrão de tokens ou o incorporado JsonUnionTypeStructuralClassifier não cumpre os teus requisitos. Um classificador personalizado pode usar outras regras estruturais para selecionar um caso de união. Registe a fábrica num destes locais:
- Atribua um delegado a JsonTypeInfo.TypeClassifier ao personalizar o contrato.
- Defina JsonUnionAttribute.TypeClassifier para uma união.
- Adicione a fábrica a JsonSerializerOptions.TypeClassifiers para serialização baseada em reflexão.
- Defina JsonSourceGenerationOptionsAttribute.TypeClassifiers num contexto de geração de código-fonte.
Um classificador lê o valor JSON atual e devolve um dos tipos de caso de JsonTypeClassifierContext.UnionCases. O serializador verifica primeiro o delegado contratado, seguido da fábrica por sindicato, das fábricas ao nível de opções e da classificação de tokens incorporada.
Para uniões ambíguas, o gerador de origem reporta um diagnóstico, a menos que um classificador esteja configurado em tempo de geração.
Lidar com valores de união nulos e predefinidos
Um sindicato pode declarar tipos de caso anuláveis. O JSON null seleciona o primeiro caso anulável. Se a união não tiver caso anulável, o JSON null produz o valor padrão da união. Para uma união de estruturas gerada pelo compilador, o valor predefinido não tem nenhum caso ativo e é serializado como JSON null.
Personalize um contrato sindical
Para cenários avançados, personalize os metadados da união através de JsonTypeInfo. O valor de JsonTypeInfo.Kind um sindicato é JsonTypeInfoKind.Union. O seu contrato expõe:
- JsonTypeInfo.UnionCases, que contém JsonUnionCaseInfo entradas.
- JsonTypeInfo.UnionConstructor, que cria uma união a partir de um tipo de caso e de um valor.
- JsonTypeInfo.UnionDeconstructor, que devolve o tipo e valor do caso ativo.
- JsonTypeInfo.TypeClassifier, que seleciona um caso durante a desserialização.
Para mais informações sobre modificação JsonTypeInfo, consulte Personalizar um contrato JSON.