Skip to content

Commit 087ef84

Browse files
committed
Deserialize boolean strings to dynamic mapping (#4127)
This commit introduces a custom formatter for Union<bool,DynamicMapping>. A boolean value may be returned as a "true" or "false" string, which should be handled correctly. Closes #4124 (cherry picked from commit ca1a8e0)
1 parent c7276c7 commit 087ef84

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

src/Nest/Mapping/DynamicMapping.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System.Runtime.Serialization;
22
using Elasticsearch.Net;
3+
using Elasticsearch.Net.Utf8Json;
4+
using Elasticsearch.Net.Utf8Json.Internal;
35

46

57
namespace Nest
@@ -13,4 +15,60 @@ public enum DynamicMapping
1315
[EnumMember(Value = "strict")]
1416
Strict
1517
}
18+
19+
internal class DynamicMappingFormatter : IJsonFormatter<Union<bool,DynamicMapping>>
20+
{
21+
private static readonly AutomataDictionary Values = new AutomataDictionary { { "true", 0 }, { "false", 1 }, { "strict", 2 } };
22+
23+
public void Serialize(ref JsonWriter writer, Union<bool, DynamicMapping> value, IJsonFormatterResolver formatterResolver)
24+
{
25+
if (value == null)
26+
{
27+
writer.WriteNull();
28+
return;
29+
}
30+
31+
switch (value.Tag)
32+
{
33+
case 0:
34+
writer.WriteBoolean(value.Item1);
35+
break;
36+
case 1:
37+
writer.WriteString(value.Item2.GetStringValue());
38+
break;
39+
}
40+
}
41+
42+
public Union<bool, DynamicMapping> Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
43+
{
44+
if (reader.ReadIsNull())
45+
return null;
46+
47+
var token = reader.GetCurrentJsonToken();
48+
switch (token)
49+
{
50+
case JsonToken.True:
51+
case JsonToken.False:
52+
return new Union<bool, DynamicMapping>(reader.ReadBoolean());
53+
case JsonToken.String:
54+
var segment = reader.ReadStringSegmentUnsafe();
55+
if (Values.TryGetValue(segment, out var value))
56+
{
57+
switch (value)
58+
{
59+
case 0:
60+
return new Union<bool, DynamicMapping>(true);
61+
case 1:
62+
return new Union<bool, DynamicMapping>(false);
63+
case 2:
64+
return new Union<bool, DynamicMapping>(DynamicMapping.Strict);
65+
}
66+
}
67+
68+
return null;
69+
default:
70+
throw new JsonParsingException($"Cannot parse Union<bool, DynamicMapping> from token '{token}'");
71+
}
72+
}
73+
}
1674
}

src/Nest/Mapping/TypeMapping.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public interface ITypeMapping
2727
/// will result in an error if an unknown field is encountered in a document.
2828
/// </summary>
2929
[DataMember(Name = "dynamic")]
30+
[JsonFormatter(typeof(DynamicMappingFormatter))]
3031
Union<bool, DynamicMapping> Dynamic { get; set; }
3132

3233
/// <summary>

src/Nest/Mapping/Types/Complex/Object/ObjectProperty.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public interface IObjectProperty : ICoreProperty
1616
/// Default is <c>true</c>
1717
/// </summary>
1818
[DataMember(Name = "dynamic")]
19+
[JsonFormatter(typeof(DynamicMappingFormatter))]
1920
Union<bool, DynamicMapping> Dynamic { get; set; }
2021

2122
/// <summary>

src/Tests/Tests.Core/ManagedElasticsearch/NodeSeeders/DefaultSeeder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ public static ITypeMapping ProjectTypeMappings(TypeMappingDescriptor<Project> m)
227227
.AutoMap()
228228
.Name(p => p.Committer)
229229
.Properties(DeveloperProperties)
230+
.Dynamic()
230231
)
231232
.Text(t => t
232233
.Name(p => p.ProjectName)

0 commit comments

Comments
 (0)