Beispiel #1
0
    public override TMessage?Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var d = JsonDocument.ParseValue(ref reader);
        if (!d.RootElement.TryGetProperty(AnyTypeUrlField, out var urlField))
        {
            throw new InvalidOperationException("Any message with no @type.");
        }

        var typeUrl  = urlField.GetString();
        var typeName = Any.GetTypeName(typeUrl);

        var descriptor = Context.TypeRegistry.Find(typeName);

        if (descriptor == null)
        {
            throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'.");
        }

        IMessage data;

        if (ServiceDescriptorHelpers.IsWellKnownType(descriptor))
        {
            if (!d.RootElement.TryGetProperty(AnyWellKnownTypeValueField, out var valueField))
            {
                throw new InvalidOperationException($"Expected '{AnyWellKnownTypeValueField}' property for well-known type Any body.");
            }

            data = (IMessage)JsonSerializer.Deserialize(valueField, descriptor.ClrType, options) !;
        }
        else
        {
            data = (IMessage)JsonSerializer.Deserialize(d.RootElement, descriptor.ClrType, options) !;
        }

        var message = new TMessage();

        message.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.SetValue(message, typeUrl);
        message.Descriptor.Fields[Any.ValueFieldNumber].Accessor.SetValue(message, data.ToByteString());

        return(message);
    }
Beispiel #2
0
    public override void Write(Utf8JsonWriter writer, TMessage value, JsonSerializerOptions options)
    {
        var typeUrl    = (string)value.Descriptor.Fields[Any.TypeUrlFieldNumber].Accessor.GetValue(value);
        var data       = (ByteString)value.Descriptor.Fields[Any.ValueFieldNumber].Accessor.GetValue(value);
        var typeName   = Any.GetTypeName(typeUrl);
        var descriptor = Context.TypeRegistry.Find(typeName);

        if (descriptor == null)
        {
            throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'.");
        }
        var valueMessage = descriptor.Parser.ParseFrom(data);

        writer.WriteStartObject();
        writer.WriteString(AnyTypeUrlField, typeUrl);

        if (ServiceDescriptorHelpers.IsWellKnownType(descriptor))
        {
            writer.WritePropertyName(AnyWellKnownTypeValueField);
            if (ServiceDescriptorHelpers.IsWrapperType(descriptor))
            {
                var wrappedValue = valueMessage.Descriptor.Fields[JsonConverterHelper.WrapperValueFieldNumber].Accessor.GetValue(valueMessage);
                JsonSerializer.Serialize(writer, wrappedValue, wrappedValue.GetType(), options);
            }
            else
            {
                JsonSerializer.Serialize(writer, valueMessage, valueMessage.GetType(), options);
            }
        }
        else
        {
            MessageConverter <Any> .WriteMessageFields(writer, valueMessage, Context.Settings, options);
        }

        writer.WriteEndObject();
    }
    private DataContract ConvertMessage(MessageDescriptor messageDescriptor)
    {
        if (ServiceDescriptorHelpers.IsWellKnownType(messageDescriptor))
        {
            if (ServiceDescriptorHelpers.IsWrapperType(messageDescriptor))
            {
                var field = messageDescriptor.Fields[Int32Value.ValueFieldNumber];

                return(_innerContractResolver.GetDataContractForType(MessageDescriptorHelpers.ResolveFieldType(field)));
            }
            if (messageDescriptor.FullName == Timestamp.Descriptor.FullName ||
                messageDescriptor.FullName == Duration.Descriptor.FullName ||
                messageDescriptor.FullName == FieldMask.Descriptor.FullName)
            {
                return(DataContract.ForPrimitive(messageDescriptor.ClrType, DataType.String, dataFormat: null));
            }
            if (messageDescriptor.FullName == Struct.Descriptor.FullName)
            {
                return(DataContract.ForObject(messageDescriptor.ClrType, Array.Empty <DataProperty>(), extensionDataType: typeof(Value)));
            }
            if (messageDescriptor.FullName == ListValue.Descriptor.FullName)
            {
                return(DataContract.ForArray(messageDescriptor.ClrType, typeof(Value)));
            }
            if (messageDescriptor.FullName == Value.Descriptor.FullName)
            {
                return(DataContract.ForPrimitive(messageDescriptor.ClrType, DataType.Unknown, dataFormat: null));
            }
            if (messageDescriptor.FullName == Any.Descriptor.FullName)
            {
                var anyProperties = new List <DataProperty>
                {
                    new DataProperty("@type", typeof(string), isRequired: true)
                };
                return(DataContract.ForObject(messageDescriptor.ClrType, anyProperties, extensionDataType: typeof(Value)));
            }
        }

        var properties = new List <DataProperty>();

        foreach (var field in messageDescriptor.Fields.InFieldNumberOrder())
        {
            // Enum type will later be used to call this contract resolver.
            // Register the enum type so we know to resolve its names from the descriptor.
            if (field.FieldType == FieldType.Enum)
            {
                _enumTypeMapping.TryAdd(field.EnumType.ClrType, field.EnumType);
            }

            Type fieldType;
            if (field.IsMap)
            {
                var mapFields = field.MessageType.Fields.InFieldNumberOrder();
                var valueType = MessageDescriptorHelpers.ResolveFieldType(mapFields[1]);
                fieldType = typeof(IDictionary <,>).MakeGenericType(typeof(string), valueType);
            }
            else if (field.IsRepeated)
            {
                fieldType = typeof(IList <>).MakeGenericType(MessageDescriptorHelpers.ResolveFieldType(field));
            }
            else
            {
                fieldType = MessageDescriptorHelpers.ResolveFieldType(field);
            }

            var propertyName = ServiceDescriptorHelpers.FormatUnderscoreName(field.Name, pascalCase: true, preservePeriod: false);
            var propertyInfo = messageDescriptor.ClrType.GetProperty(propertyName);

            properties.Add(new DataProperty(field.JsonName, fieldType, memberInfo: propertyInfo));
        }

        var schema = DataContract.ForObject(messageDescriptor.ClrType, properties: properties);

        return(schema);
    }