Azure / autorest.csharp

Extension for AutoRest (https://github.com/Azure/autorest) that generates C# code
MIT License
140 stars 160 forks source link

[Feature] support AdditionalProperties #3454

Closed chunyu3 closed 6 months ago

chunyu3 commented 1 year ago

DPG will support a model which may contain addition properties.

AdditionalProperties definition in spec

  1. swagger
    "Foo": {
      "type": "object",
      "properties": {
        "known": {
          "type": "string"
        }
      },
      "required": [
        "known"
      ],
      "additionalProperties": true
    }
  2. typespec (under discussion)
    
    model Foo extends Record<unknown> {
    known: string;
    }

model Foo is Record { @doc("The name property") known: string; }



DPG will generate a model which may accept additional properties.
chunyu3 commented 1 year ago

Model generated

same as HLC

    public partial class TestModel
    {
        /// <summary> Initializes a new instance of TestModel. </summary>
        public TestModel()
        {
            AdditionalProperties = new ChangeTrackingDictionary<string, object>();
        }

        /// <summary> Initializes a new instance of TestModel. </summary>
        /// <param name="id"></param>
        /// <param name="name"></param>
        /// <param name="additionalProperties"> Additional Properties. </param>
        internal TestModel(string id, string name, IDictionary<string, object> additionalProperties)
        {
            Id = id;
            Name = name;
            AdditionalProperties = additionalProperties;
        }

        /// <summary> Gets or sets the id. </summary>
        public string Id { get; set; }
        /// <summary> Gets or sets the name. </summary>
        public string Name { get; set; }
        /// <summary> Additional Properties. </summary>
        public IDictionary<string, object> AdditionalProperties { get; }
    }

    public partial class TestModel : IUtf8JsonSerializable
    {
        void IUtf8JsonSerializable.Write(Utf8JsonWriter writer)
        {
            writer.WriteStartObject();
            if (Optional.IsDefined(Id))
            {
                writer.WritePropertyName("id"u8);
                writer.WriteStringValue(Id);
            }
            if (Optional.IsDefined(Name))
            {
                writer.WritePropertyName("name"u8);
                writer.WriteStringValue(Name);
            }
            foreach (var item in AdditionalProperties)
            {
                writer.WritePropertyName(item.Key);
                writer.WriteObjectValue(item.Value);
            }
            writer.WriteEndObject();
        }

        internal static TestModel DeserializeTestModel(JsonElement element)
        {
            if (element.ValueKind == JsonValueKind.Null)
            {
                return null;
            }
            Optional<string> id = default;
            Optional<string> name = default;
            IDictionary<string, object> additionalProperties = default;
            Dictionary<string, object> additionalPropertiesDictionary = new Dictionary<string, object>();
            foreach (var property in element.EnumerateObject())
            {
                if (property.NameEquals("id"u8))
                {
                    id = property.Value.GetString();
                    continue;
                }
                if (property.NameEquals("name"u8))
                {
                    name = property.Value.GetString();
                    continue;
                }
                additionalPropertiesDictionary.Add(property.Name, property.Value.GetObject());
            }
            additionalProperties = additionalPropertiesDictionary;
            return new TestModel(id.Value, name.Value, additionalProperties);
        }
    }
chunyu3 commented 1 year ago

How to create Model

var additionalProps = new AdditionalPropertiesWithRawData("name")
{
    additionalProperties = { { "time", "12:00" }, { "age", 12 } }
};
chunyu3 commented 1 year ago

In HLC, additinalProperties is Dictionary<string, object>, in DPG it will be Dictionary<string, BinaryData>

lirenhe commented 11 months ago

Need to clarify the meaning of 'model A extends/is Record < string >'

chunyu3 commented 11 months ago

option 1: model Foo { known: string; additionalProperties: Record; } option2: use decorator

chunyu3 commented 10 months ago

Typespec definition is not ready.

chunyu3 commented 7 months ago

remaining task: in emitter, parse the AdditionalPreooperties typspec type to Dictionary InputType