Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate object type value giving unexpexced results #5971

Open
Skulek opened this issue Jan 8, 2025 · 8 comments
Open

Generate object type value giving unexpexced results #5971

Skulek opened this issue Jan 8, 2025 · 8 comments
Labels
Csharp Pull requests that update .net code status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close type:question An issue that's a question

Comments

@Skulek
Copy link

Skulek commented Jan 8, 2025

Hello,
I have a problem with generating the Request object with property type of object.

public sealed record EncryptRequest
{
    public object? Value { get; set; }

    public string? DataType { get; set; }

    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public Dictionary<string, string>? Properties { get; set; }

    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public Dictionary<string, object>? ContextItems { get; set; }
}

I have a specification from swagger.json that clearly says that it should be an object

"encryptRequest": {
      "type": "object",
      "properties": {
        "value": {
          "type": "object"
        },
        "dataType": {
          "type": "string"
        },
        "properties": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "contextItems": {
          "type": "object",
          "additionalProperties": {
            "type": "object"
          }
        }
      }
    }

but after kiota generation i dont have an access to fill in that value. This is the result of generation

namespace Cryptography.Models
{
    [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
    #pragma warning disable CS1591
    public partial class EncryptRequest : IAdditionalDataHolder, IParsable
    #pragma warning restore CS1591
    {
        /// <summary>Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.</summary>
        public IDictionary<string, object> AdditionalData { get; set; }
        /// <summary>The contextItems property</summary>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
        public global::Cryptography.Models.EncryptRequest_contextItems? ContextItems { get; set; }
#nullable restore
#else
        public global::Cryptography.Models.EncryptRequest_contextItems ContextItems { get; set; }
#endif
        /// <summary>The dataType property</summary>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
        public string? DataType { get; set; }
#nullable restore
#else
        public string DataType { get; set; }
#endif
        /// <summary>The properties property</summary>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
        public global::Cryptography.Models.EncryptRequest_properties? Properties { get; set; }
#nullable restore
#else
        public global::Cryptography.Models.EncryptRequest_properties Properties { get; set; }
#endif
        /// <summary>The value property</summary>
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
#nullable enable
        public global::Cryptography.Models.EncryptRequest_value? Value { get; set; }
#nullable restore
#else
        public global::Cryptography.Models.EncryptRequest_value Value { get; set; }
#endif
        /// <summary>
        /// Instantiates a new <see cref="global::Cryptography.Models.EncryptRequest"/> and sets the default values.
        /// </summary>
        public EncryptRequest()
        {
            AdditionalData = new Dictionary<string, object>();
        }
        /// <summary>
        /// Creates a new instance of the appropriate class based on discriminator value
        /// </summary>
        /// <returns>A <see cref="global::Cryptography.Models.EncryptRequest"/></returns>
        /// <param name="parseNode">The parse node to use to read the discriminator value and create the object</param>
        public static global::Cryptography.Models.EncryptRequest CreateFromDiscriminatorValue(IParseNode parseNode)
        {
            _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode));
            return new global::Cryptography.Models.EncryptRequest();
        }
        /// <summary>
        /// The deserialization information for the current model
        /// </summary>
        /// <returns>A IDictionary&lt;string, Action&lt;IParseNode&gt;&gt;</returns>
        public virtual IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
        {
            return new Dictionary<string, Action<IParseNode>>
            {
                { "contextItems", n => { ContextItems = n.GetObjectValue<global::Cryptography.Models.EncryptRequest_contextItems>(global::Cryptography.Models.EncryptRequest_contextItems.CreateFromDiscriminatorValue); } },
                { "dataType", n => { DataType = n.GetStringValue(); } },
                { "properties", n => { Properties = n.GetObjectValue<global::Cryptography.Models.EncryptRequest_properties>(global::Cryptography.Models.EncryptRequest_properties.CreateFromDiscriminatorValue); } },
                { "value", n => { Value = n.GetObjectValue<global::Cryptography.Models.EncryptRequest_value>(global::Cryptography.Models.EncryptRequest_value.CreateFromDiscriminatorValue); } },
            };
        }
        /// <summary>
        /// Serializes information the current object
        /// </summary>
        /// <param name="writer">Serialization writer to use to serialize this model</param>
        public virtual void Serialize(ISerializationWriter writer)
        {
            _ = writer ?? throw new ArgumentNullException(nameof(writer));
            writer.WriteObjectValue<global::Cryptography.Models.EncryptRequest_contextItems>("contextItems", ContextItems);
            writer.WriteStringValue("dataType", DataType);
            writer.WriteObjectValue<global::Cryptography.Models.EncryptRequest_properties>("properties", Properties);
            writer.WriteObjectValue<global::Cryptography.Models.EncryptRequest_value>("value", Value);
            writer.WriteAdditionalData(AdditionalData);
        }
    }
}
#pragma warning restore CS0618`
namespace Cryptography.Models
{
    [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
    #pragma warning disable CS1591
    public partial class EncryptRequest_value : IAdditionalDataHolder, IParsable
    #pragma warning restore CS1591
    {
        /// <summary>Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.</summary>
        public IDictionary<string, object> AdditionalData { get; set; }
        /// <summary>
        /// Instantiates a new <see cref="global::Cryptography.Models.EncryptRequest_value"/> and sets the default values.
        /// </summary>
        public EncryptRequest_value()
        {
            AdditionalData = new Dictionary<string, object>();
        }
        /// <summary>
        /// Creates a new instance of the appropriate class based on discriminator value
        /// </summary>
        /// <returns>A <see cref="global::Cryptography.Models.EncryptRequest_value"/></returns>
        /// <param name="parseNode">The parse node to use to read the discriminator value and create the object</param>
        public static global::Cryptography.Models.EncryptRequest_value CreateFromDiscriminatorValue(IParseNode parseNode)
        {
            _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode));
            return new global::Cryptography.Models.EncryptRequest_value();
        }
        /// <summary>
        /// The deserialization information for the current model
        /// </summary>
        /// <returns>A IDictionary&lt;string, Action&lt;IParseNode&gt;&gt;</returns>
        public virtual IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
        {
            return new Dictionary<string, Action<IParseNode>>
            {
            };
        }
        /// <summary>
        /// Serializes information the current object
        /// </summary>
        /// <param name="writer">Serialization writer to use to serialize this model</param>
        public virtual void Serialize(ISerializationWriter writer)
        {
            _ = writer ?? throw new ArgumentNullException(nameof(writer));
            writer.WriteAdditionalData(AdditionalData);
        }
    }
}
@github-project-automation github-project-automation bot moved this to Needs Triage 🔍 in Kiota Jan 8, 2025
@baywet
Copy link
Member

baywet commented Jan 8, 2025

Hi @Skulek
Thank you for using kiota and for reaching out.

This is working as expected:

  • Kiota generates a class type, with the additional data field so there's "a place to store the information" coming back from the service.
  • Kiota generates that name, since the object is a nested property.

Let us know if you have any additional comments or questions.

@baywet baywet added Csharp Pull requests that update .net code status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close type:question An issue that's a question labels Jan 8, 2025
@baywet baywet moved this from Needs Triage 🔍 to Waits for author 🔁 in Kiota Jan 8, 2025
@Skulek
Copy link
Author

Skulek commented Jan 8, 2025

Thank you for your quick response @baywet !
So - the question is how we should instatiate that value ?

var httpClient = new HttpClient();
var adapter = new HttpClientRequestAdapter(new AnonymousAuthenticationProvider(), httpClient: httpClient);
adapter.BaseUrl = "http://localhost:7053";

var client = new CryptographyClient(adapter);

try
{
    // Encrypt
    var encryptResponse = await client.Encrypt.PostAsync(new EncryptRequest
    {
   // Value = "Test", 
   Value = new EncryptRequest_value()
    });
    Console.WriteLine($"Encrypted: {encryptResponse.Data}");
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Attention 👋 and removed status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close labels Jan 8, 2025
@baywet
Copy link
Member

baywet commented Jan 8, 2025

Thank you for the additional information.

The snippet you've provided looks correct, do you get any error?

@baywet baywet added status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close and removed Needs: Attention 👋 labels Jan 8, 2025
@Skulek
Copy link
Author

Skulek commented Jan 8, 2025

Yes - it seems to be coreccted but for example how I should assign to the new EncryptRequest_value() value "test" ? because the first, commented out code doesn't seem to work
Image

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Attention 👋 and removed status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close labels Jan 8, 2025
@baywet
Copy link
Member

baywet commented Jan 8, 2025

Thank you for the additional information.

Could you please share what resulting payload you'd expect?

@baywet baywet added status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close and removed Needs: Attention 👋 labels Jan 8, 2025
@Skulek
Copy link
Author

Skulek commented Jan 8, 2025

@baywet - sorry but I don't quite understand tbh.
I just wanted to create a simple object based on created from kiota object mentioned above

public sealed record EncryptRequest
{
    public object? Value { get; set; }

    public string? DataType { get; set; }

    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public Dictionary<string, string>? Properties { get; set; }

    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public Dictionary<string, object>? ContextItems { get; set; }
}

i just want from the client itself create simple request like

 // Encrypt
 var encryptResponse = await client.Encrypt.PostAsync(new EncryptRequest
 {
// Value = "Test", 
     Value = new EncryptRequest_value("test"),
     DataType = "string",
 });
 Console.WriteLine($"Encrypted: {encryptResponse.Data}");

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Attention 👋 and removed status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close labels Jan 8, 2025
@Skulek
Copy link
Author

Skulek commented Jan 9, 2025

Do you happen to have any updates on that @baywet ? does my answer is enough for you ?

@andrueastman
Copy link
Member

Hey @Skulek

Given that the Value has an object type, what this means is that you can't assign a primitive value like a string or number to it. What is expected in this scenario is that an object is essentially a collection of properties(a dictionary with the property names as strings and the property values)

So, you would then have code like below leveraging the AdditionalData property

Value = new EncryptRequest_value
{
    AdditionalData = new Dictionary<string, object> 
    {
        { "stringProperty", "stringValues"},
        { "intProperty", 77},
    }
};

To have a json body produced that looks close to this

{
    "value": {
        "stringProperty": "stringValue",
        "intProperty": 77
    }
}

@andrueastman andrueastman added status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close and removed Needs: Attention 👋 labels Jan 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Csharp Pull requests that update .net code status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close type:question An issue that's a question
Projects
Status: Waits for author 🔁
Development

No branches or pull requests

3 participants