-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
Describe the bug
In these two examples the Azure Search dotnet SDK SearchIndexerSkill deserializer throws exceptions on nullable properties and empty collections.
To get around this we have to put some value of the correct type in those properties of any SearchIndexerSkill.
The deserializer:
Line 101 in a03cb7b
| internal static WebApiSkill DeserializeWebApiSkill(JsonElement element) |
Expected behavior
Users shouldn't have to provide values for optional properties.
Actual behavior and Reproduction
Example 1 - Nullable properties are required to specified:
If you don't specify what are documented and implemented as nullable properties for a SearchIndexerSkill, the deserializer will throw exceptions.
The EntityRecognitionSkill class definition for reference.
The WebApiSkill class definition for reference.
When you add this EntityRecognitionSkill to a skillset:
var entityRecognitionSkill = new EntityRecognitionSkill(inputs, outputs)
{
Context = "/document/finalText/pages/*"
};Skillset creation will throw this ArgumentNullException:
An unhandled exception of type 'System.ArgumentNullException' occurred in System.Private.CoreLib.dll: 'Value cannot be null.'
at Azure.Search.Documents.Indexes.Models.EntityRecognitionSkillLanguage..ctor(String value) at Azure.Search.Documents.Indexes.Models.EntityRecognitionSkill.DeserializeEntityRecognitionSkill(JsonElement element) at Azure.Search.Documents.Indexes.Models.SearchIndexerSkill.DeserializeSearchIndexerSkill(JsonElement element) at Azure.Search.Documents.Indexes.Models.SearchIndexerSkillset.DeserializeSearchIndexerSkillset(JsonElement element) at Azure.Search.Documents.SkillsetsRestClient.Create(SearchIndexerSkillset skillset, CancellationToken cancellationToken) at Azure.Search.Documents.Indexes.SearchIndexerClient.CreateSkillset(SearchIndexerSkillset skillset, CancellationToken cancellationToken)
An unhandled exception of type 'System.ArgumentNullException' occurred in System.Private.CoreLib.dll: 'Value cannot be null.'
at Azure.Search.Documents.Indexes.Models.EntityRecognitionSkillLanguage..ctor(String value) at Azure.Search.Documents.Indexes.Models.EntityRecognitionSkill.DeserializeEntityRecognitionSkill(JsonElement element) at Azure.Search.Documents.Indexes.Models.SearchIndexerSkill.DeserializeSearchIndexerSkill(JsonElement element) at Azure.Search.Documents.Indexes.Models.SearchIndexerSkillset.DeserializeSearchIndexerSkillset(JsonElement element) at Azure.Search.Documents.SkillsetsRestClient.Create(SearchIndexerSkillset skillset, CancellationToken cancellationToken) at Azure.Search.Documents.Indexes.SearchIndexerClient.CreateSkillset(SearchIndexerSkillset skillset, CancellationToken cancellationToken)
Or a WebApiSkill like this to a skillset:
var webApiSkill = new WebApiSkill(inputs, outputs, uri)
{
Description = "Upload image data to the annotation store",
Context = "/document/normalized_images/*"
};Skillset creation will throw this FormatException:
An unhandled exception of type 'System.FormatException' occurred in System.Private.CoreLib.dll: 'The string '' is not a valid TimeSpan value.'
at System.Xml.XmlConvert.ToTimeSpan(String s) at Azure.Search.Documents.Indexes.Models.WebApiSkill.DeserializeWebApiSkill(JsonElement element) at Azure.Search.Documents.Indexes.Models.SearchIndexerSkill.DeserializeSearchIndexerSkill(JsonElement element) at Azure.Search.Documents.Indexes.Models.SearchIndexerSkillset.DeserializeSearchIndexerSkillset(JsonElement element) at Azure.Search.Documents.SkillsetsRestClient.Create(SearchIndexerSkillset skillset, CancellationToken cancellationToken) at Azure.Search.Documents.Indexes.SearchIndexerClient.CreateSkillset(SearchIndexerSkillset skillset, CancellationToken cancellationToken)
If you assign values to the nullable properties of these skills like below you're able to successfully create the skillset:
var entityRecognitionSkill = new EntityRecognitionSkill(inputs, outputs)
{
Context = "/document/finalText/pages/*",
DefaultLanguageCode = EntityRecognitionSkillLanguage.En //this is a nullable that serialization enforces as required
};
var webApiSkill = new WebApiSkill(inputs, outputs, uri)
{
Description = "Upload image data to the annotation store",
Context = "/document/normalized_images/*",
BatchSize = 1, //this is a nullable that serialization enforces as required
DegreeOfParallelism = 1, //this is a nullable that serialization enforces as required
Timeout = System.TimeSpan.FromSeconds(30) //this is a nullable that serialization enforces as required
};Example 2 - An empty dictionary will throw an Invalid Operation Exception
An empty HttpHeaders dictionary in a WebApiSkill throws a InvalidOperationException at deserialization.
The WebApiSkill class definition for reference
When you add this WebApiSkill to a skillset:
var webApiSkill = new WebApiSkill(inputs, outputs, uri)
{
Description = "Generate HOCR for webpage rendering",
Context = "/document",
BatchSize = 1, //this is a nullable that serialization enforces as required
DegreeOfParallelism = 1, //this is a nullable that serialization enforces as required
Timeout = System.TimeSpan.FromSeconds(30), //this is a nullable that serialization enforces as required
};The skillset creation will throw this InvalidOperationException:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Private.CoreLib.dll: 'The requested operation requires an element of type 'Object', but the target element has type 'Null'.'
at System.Text.Json.JsonElement.EnumerateObject() at Azure.Search.Documents.Indexes.Models.WebApiSkill.DeserializeWebApiSkill(JsonElement element) at Azure.Search.Documents.Indexes.Models.SearchIndexerSkill.DeserializeSearchIndexerSkill(JsonElement element) at Azure.Search.Documents.Indexes.Models.SearchIndexerSkillset.DeserializeSearchIndexerSkillset(JsonElement element) at Azure.Search.Documents.SkillsetsRestClient.Create(SearchIndexerSkillset skillset, CancellationToken cancellationToken) at Azure.Search.Documents.Indexes.SearchIndexerClient.CreateSkillset(SearchIndexerSkillset skillset, CancellationToken cancellationToken)
To get the skillset to create, you have to put some value in the dictionary even if you don't need it:
var webApiSkill = new WebApiSkill(inputs, outputs, uri)
{
Description = "Generate HOCR for webpage rendering",
Context = "/document",
BatchSize = 1, //this is a nullable that serialization enforces as required
DegreeOfParallelism = 1, //this is a nullable that serialization enforces as required
Timeout = System.TimeSpan.FromSeconds(30), //this is a nullable that serialization enforces as required
};
//this dictionary requires _some_ value
webApiSkill.HttpHeaders["foo"] = "bar";Environment:
-
Name and version of the Library package used:
- Azure.Search.Documents 11.1.1
-
Hosting platform or OS and .NET runtime version:
.NET Core SDK (reflecting any global.json):
Version: 3.1.401
Commit: 39d17847db
Runtime Environment:
OS Name: ubuntu
OS Version: 20.04
OS Platform: Linux
RID: ubuntu.20.04-x64
- IDE and version:
- Visual Studio Code Version: 1.49.0