@@ -549,12 +549,14 @@ private static void parseObject(final ParseContext context, ObjectMapper mapper,
549
549
Tuple <Integer , ObjectMapper > parentMapperTuple = getDynamicParentMapper (context , paths , mapper );
550
550
ObjectMapper parentMapper = parentMapperTuple .v2 ();
551
551
ObjectMapper .Dynamic dynamic = dynamicOrDefault (parentMapper , context );
552
+
553
+ Mapper .Builder builder = null ;
552
554
switch (dynamic ) {
553
555
case STRICT :
554
556
throw new StrictDynamicMappingException (dynamic .name ().toLowerCase (Locale .ROOT ), mapper .fullPath (), currentFieldName );
555
557
case TRUE :
556
558
case STRICT_ALLOW_TEMPLATES :
557
- Mapper . Builder builder = findTemplateBuilder (
559
+ builder = findTemplateBuilder (
558
560
context ,
559
561
currentFieldName ,
560
562
XContentFieldType .OBJECT ,
@@ -572,6 +574,26 @@ private static void parseObject(final ParseContext context, ObjectMapper mapper,
572
574
parseObjectOrField (context , objectMapper );
573
575
context .path ().remove ();
574
576
break ;
577
+ case FALSE_ALLOW_TEMPLATES :
578
+ builder = findTemplateBuilder (
579
+ context ,
580
+ currentFieldName ,
581
+ XContentFieldType .OBJECT ,
582
+ dynamic ,
583
+ mapper .fullPath ()
584
+ );
585
+
586
+ if (builder == null ) {
587
+ context .parser ().skipChildren ();
588
+ } else {
589
+ Mapper .BuilderContext templateBuilderContext = new Mapper .BuilderContext (context .indexSettings ().getSettings (), context .path ());
590
+ objectMapper = builder .build (templateBuilderContext );
591
+ context .addDynamicMapper (objectMapper );
592
+ context .path ().add (currentFieldName );
593
+ parseObjectOrField (context , objectMapper );
594
+ context .path ().remove ();
595
+ }
596
+ break ;
575
597
case FALSE :
576
598
// not dynamic, read everything up to end object
577
599
context .parser ().skipChildren ();
@@ -605,6 +627,7 @@ private static void parseArray(ParseContext context, ObjectMapper parentMapper,
605
627
Tuple <Integer , ObjectMapper > parentMapperTuple = getDynamicParentMapper (context , paths , parentMapper );
606
628
parentMapper = parentMapperTuple .v2 ();
607
629
ObjectMapper .Dynamic dynamic = dynamicOrDefault (parentMapper , context );
630
+ Mapper .Builder builder = null ;
608
631
switch (dynamic ) {
609
632
case STRICT :
610
633
throw new StrictDynamicMappingException (
@@ -614,7 +637,7 @@ private static void parseArray(ParseContext context, ObjectMapper parentMapper,
614
637
);
615
638
case TRUE :
616
639
case STRICT_ALLOW_TEMPLATES :
617
- Mapper . Builder builder = findTemplateBuilder (
640
+ builder = findTemplateBuilder (
618
641
context ,
619
642
arrayFieldName ,
620
643
XContentFieldType .OBJECT ,
@@ -640,6 +663,33 @@ private static void parseArray(ParseContext context, ObjectMapper parentMapper,
640
663
}
641
664
}
642
665
break ;
666
+ case FALSE_ALLOW_TEMPLATES :
667
+ builder = findTemplateBuilder (
668
+ context ,
669
+ arrayFieldName ,
670
+ XContentFieldType .OBJECT ,
671
+ dynamic ,
672
+ parentMapper .fullPath ()
673
+ );
674
+ if (builder == null ) {
675
+ context .parser ().skipChildren ();
676
+ } else {
677
+ Mapper .BuilderContext templateBuilderContext = new Mapper .BuilderContext (
678
+ context .indexSettings ().getSettings (),
679
+ context .path ()
680
+ );
681
+ mapper = builder .build (templateBuilderContext );
682
+ assert mapper != null ;
683
+ if (parsesArrayValue (mapper )) {
684
+ context .addDynamicMapper (mapper );
685
+ context .path ().add (arrayFieldName );
686
+ parseObjectOrField (context , mapper );
687
+ context .path ().remove ();
688
+ } else {
689
+ parseNonDynamicArray (context , parentMapper , lastFieldName , arrayFieldName );
690
+ }
691
+ }
692
+ break ;
643
693
case FALSE :
644
694
// TODO: shouldn't this skip, not parse?
645
695
parseNonDynamicArray (context , parentMapper , lastFieldName , arrayFieldName );
@@ -786,12 +836,18 @@ private static Mapper.Builder<?> createBuilderFromDynamicValue(
786
836
if (parseableAsLong && context .root ().numericDetection ()) {
787
837
Mapper .Builder builder = findTemplateBuilder (context , currentFieldName , XContentFieldType .LONG , dynamic , fullPath );
788
838
if (builder == null ) {
839
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
840
+ return null ;
841
+ }
789
842
builder = newLongBuilder (currentFieldName , context .indexSettings ().getSettings ());
790
843
}
791
844
return builder ;
792
845
} else if (parseableAsDouble && context .root ().numericDetection ()) {
793
846
Mapper .Builder builder = findTemplateBuilder (context , currentFieldName , XContentFieldType .DOUBLE , dynamic , fullPath );
794
847
if (builder == null ) {
848
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
849
+ return null ;
850
+ }
795
851
builder = newFloatBuilder (currentFieldName , context .indexSettings ().getSettings ());
796
852
}
797
853
return builder ;
@@ -808,6 +864,9 @@ private static Mapper.Builder<?> createBuilderFromDynamicValue(
808
864
}
809
865
Mapper .Builder builder = findTemplateBuilder (context , currentFieldName , dateTimeFormatter , dynamic , fullPath );
810
866
if (builder == null ) {
867
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
868
+ return null ;
869
+ }
811
870
boolean ignoreMalformed = IGNORE_MALFORMED_SETTING .get (context .indexSettings ().getSettings ());
812
871
builder = new DateFieldMapper .Builder (
813
872
currentFieldName ,
@@ -824,6 +883,9 @@ private static Mapper.Builder<?> createBuilderFromDynamicValue(
824
883
825
884
Mapper .Builder builder = findTemplateBuilder (context , currentFieldName , XContentFieldType .STRING , dynamic , fullPath );
826
885
if (builder == null ) {
886
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
887
+ return null ;
888
+ }
827
889
builder = new TextFieldMapper .Builder (currentFieldName , context .mapperService ().getIndexAnalyzers ()).addMultiField (
828
890
new KeywordFieldMapper .Builder ("keyword" ).ignoreAbove (256 )
829
891
);
@@ -836,6 +898,9 @@ private static Mapper.Builder<?> createBuilderFromDynamicValue(
836
898
|| numberType == XContentParser .NumberType .BIG_INTEGER ) {
837
899
Mapper .Builder builder = findTemplateBuilder (context , currentFieldName , XContentFieldType .LONG , dynamic , fullPath );
838
900
if (builder == null ) {
901
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
902
+ return null ;
903
+ }
839
904
builder = newLongBuilder (currentFieldName , context .indexSettings ().getSettings ());
840
905
}
841
906
return builder ;
@@ -844,6 +909,9 @@ private static Mapper.Builder<?> createBuilderFromDynamicValue(
844
909
|| numberType == XContentParser .NumberType .BIG_DECIMAL ) {
845
910
Mapper .Builder builder = findTemplateBuilder (context , currentFieldName , XContentFieldType .DOUBLE , dynamic , fullPath );
846
911
if (builder == null ) {
912
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
913
+ return null ;
914
+ }
847
915
// no templates are defined, we use float by default instead of double
848
916
// since this is much more space-efficient and should be enough most of
849
917
// the time
@@ -854,12 +922,18 @@ private static Mapper.Builder<?> createBuilderFromDynamicValue(
854
922
} else if (token == XContentParser .Token .VALUE_BOOLEAN ) {
855
923
Mapper .Builder builder = findTemplateBuilder (context , currentFieldName , XContentFieldType .BOOLEAN , dynamic , fullPath );
856
924
if (builder == null ) {
925
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
926
+ return null ;
927
+ }
857
928
builder = new BooleanFieldMapper .Builder (currentFieldName );
858
929
}
859
930
return builder ;
860
931
} else if (token == XContentParser .Token .VALUE_EMBEDDED_OBJECT ) {
861
932
Mapper .Builder builder = findTemplateBuilder (context , currentFieldName , XContentFieldType .BINARY , dynamic , fullPath );
862
933
if (builder == null ) {
934
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
935
+ return null ;
936
+ }
863
937
builder = new BinaryFieldMapper .Builder (currentFieldName );
864
938
}
865
939
return builder ;
@@ -868,6 +942,9 @@ private static Mapper.Builder<?> createBuilderFromDynamicValue(
868
942
if (builder != null ) {
869
943
return builder ;
870
944
}
945
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES ) {
946
+ return null ;
947
+ }
871
948
}
872
949
// TODO how do we identify dynamically that its a binary value?
873
950
throw new IllegalStateException (
@@ -882,14 +959,23 @@ private static void parseDynamicValue(
882
959
XContentParser .Token token
883
960
) throws IOException {
884
961
ObjectMapper .Dynamic dynamic = dynamicOrDefault (parentMapper , context );
962
+
885
963
if (dynamic == ObjectMapper .Dynamic .STRICT ) {
886
964
throw new StrictDynamicMappingException (dynamic .name ().toLowerCase (Locale .ROOT ), parentMapper .fullPath (), currentFieldName );
887
965
}
888
966
if (dynamic == ObjectMapper .Dynamic .FALSE ) {
889
967
return ;
890
968
}
891
- final Mapper .BuilderContext builderContext = new Mapper .BuilderContext (context .indexSettings ().getSettings (), context .path ());
892
969
final Mapper .Builder <?> builder = createBuilderFromDynamicValue (context , token , currentFieldName , dynamic , parentMapper .fullPath ());
970
+ if (dynamic == ObjectMapper .Dynamic .FALSE_ALLOW_TEMPLATES && builder == null ) {
971
+ // For FALSE_ALLOW_TEMPLATES, if no template matches, we still need to consume the token
972
+ // to maintain proper JSON parsing state
973
+ if (token == XContentParser .Token .START_OBJECT || token == XContentParser .Token .START_ARRAY ) {
974
+ context .parser ().skipChildren ();
975
+ }
976
+ return ;
977
+ }
978
+ final Mapper .BuilderContext builderContext = new Mapper .BuilderContext (context .indexSettings ().getSettings (), context .path ());
893
979
Mapper mapper = builder .build (builderContext );
894
980
context .addDynamicMapper (mapper );
895
981
@@ -975,12 +1061,13 @@ private static Tuple<Integer, ObjectMapper> getDynamicParentMapper(
975
1061
// One mapping is missing, check if we are allowed to create a dynamic one.
976
1062
ObjectMapper .Dynamic dynamic = dynamicOrDefault (parent , context );
977
1063
1064
+ Mapper .Builder builder = null ;
978
1065
switch (dynamic ) {
979
1066
case STRICT :
980
1067
throw new StrictDynamicMappingException (dynamic .name ().toLowerCase (Locale .ROOT ), parent .fullPath (), paths [i ]);
981
1068
case STRICT_ALLOW_TEMPLATES :
982
1069
case TRUE :
983
- Mapper . Builder builder = findTemplateBuilder (
1070
+ builder = findTemplateBuilder (
984
1071
context ,
985
1072
paths [i ],
986
1073
XContentFieldType .OBJECT ,
@@ -1004,6 +1091,31 @@ private static Tuple<Integer, ObjectMapper> getDynamicParentMapper(
1004
1091
}
1005
1092
context .addDynamicMapper (mapper );
1006
1093
break ;
1094
+ case FALSE_ALLOW_TEMPLATES :
1095
+ builder = findTemplateBuilder (
1096
+ context ,
1097
+ paths [i ],
1098
+ XContentFieldType .OBJECT ,
1099
+ dynamic ,
1100
+ parent .fullPath ()
1101
+ );
1102
+ if (builder == null ) {
1103
+ return new Tuple <>(pathsAdded , parent );
1104
+ }
1105
+ Mapper .BuilderContext templateBuilderContext = new Mapper .BuilderContext (
1106
+ context .indexSettings ().getSettings (),
1107
+ context .path ()
1108
+ );
1109
+ mapper = (ObjectMapper ) builder .build (templateBuilderContext );
1110
+ if (mapper .nested () != ObjectMapper .Nested .NO ) {
1111
+ throw new MapperParsingException (
1112
+ "It is forbidden to create dynamic nested objects (["
1113
+ + context .path ().pathAsText (paths [i ])
1114
+ + "]) through `copy_to` or dots in field names"
1115
+ );
1116
+ }
1117
+ context .addDynamicMapper (mapper );
1118
+ break ;
1007
1119
case FALSE :
1008
1120
// Should not dynamically create any more mappers so return the last mapper
1009
1121
return new Tuple <>(pathsAdded , parent );
@@ -1079,6 +1191,7 @@ private static Mapper.Builder findTemplateBuilder(
1079
1191
String fieldFullPath
1080
1192
) {
1081
1193
Mapper .Builder builder = context .root ().findTemplateBuilder (context , name , matchType );
1194
+
1082
1195
if (builder == null && dynamic == ObjectMapper .Dynamic .STRICT_ALLOW_TEMPLATES ) {
1083
1196
throw new StrictDynamicMappingException (dynamic .name ().toLowerCase (Locale .ROOT ), fieldFullPath , name );
1084
1197
}
0 commit comments