18
18
import org .opensearch .core .xcontent .XContentBuilder ;
19
19
import org .opensearch .core .xcontent .XContentLocation ;
20
20
import org .opensearch .core .xcontent .XContentParser ;
21
+ import org .opensearch .index .mapper .MapperParsingException ;
21
22
22
23
import java .io .IOException ;
23
24
import java .math .BigInteger ;
@@ -44,6 +45,10 @@ public class JsonToStringXContentParser extends AbstractXContentParser {
44
45
45
46
private DeprecationHandler deprecationHandler ;
46
47
48
+ private int depthLimit ;
49
+ private String nullValue ;
50
+ private int ignoreAbove ;
51
+
47
52
private static final String VALUE_AND_PATH_SUFFIX = "._valueAndPath" ;
48
53
private static final String VALUE_SUFFIX = "._value" ;
49
54
private static final String DOT_SYMBOL = "." ;
@@ -53,19 +58,25 @@ public JsonToStringXContentParser(
53
58
NamedXContentRegistry xContentRegistry ,
54
59
DeprecationHandler deprecationHandler ,
55
60
XContentParser parser ,
56
- String fieldTypeName
61
+ String fieldTypeName ,
62
+ int depthLimit ,
63
+ String nullValue ,
64
+ int ignoreAbove
57
65
) throws IOException {
58
66
super (xContentRegistry , deprecationHandler );
59
67
this .deprecationHandler = deprecationHandler ;
60
68
this .xContentRegistry = xContentRegistry ;
61
69
this .parser = parser ;
62
70
this .fieldTypeName = fieldTypeName ;
71
+ this .depthLimit = depthLimit ;
72
+ this .nullValue = nullValue ;
73
+ this .ignoreAbove = ignoreAbove ;
63
74
}
64
75
65
76
public XContentParser parseObject () throws IOException {
66
77
builder .startObject ();
67
78
StringBuilder path = new StringBuilder (fieldTypeName );
68
- parseToken (path , null );
79
+ parseToken (path , null , 1 );
69
80
builder .field (this .fieldTypeName , keyList );
70
81
builder .field (this .fieldTypeName + VALUE_SUFFIX , valueList );
71
82
builder .field (this .fieldTypeName + VALUE_AND_PATH_SUFFIX , valueAndPathList );
@@ -74,7 +85,15 @@ public XContentParser parseObject() throws IOException {
74
85
return JsonXContent .jsonXContent .createParser (this .xContentRegistry , this .deprecationHandler , String .valueOf (jString ));
75
86
}
76
87
77
- private void parseToken (StringBuilder path , String currentFieldName ) throws IOException {
88
+ private void parseToken (StringBuilder path , String currentFieldName , int depth ) throws IOException {
89
+ if (depth >= depthLimit ) {
90
+ throw new MapperParsingException (
91
+ "the depth of flat_object field path [" + path + "] is bigger than maximum" + " depth [" + depthLimit + "]"
92
+ );
93
+ }
94
+ if (depth == 1 && processNoNestedValue ()) {
95
+ return ;
96
+ }
78
97
79
98
while (this .parser .nextToken () != Token .END_OBJECT ) {
80
99
if (this .parser .currentName () != null ) {
@@ -100,12 +119,12 @@ private void parseToken(StringBuilder path, String currentFieldName) throws IOEx
100
119
this .keyList .add (fieldNameSuffix );
101
120
}
102
121
} else if (this .parser .currentToken () == Token .START_ARRAY ) {
103
- parseToken (path , currentFieldName );
122
+ parseToken (path , currentFieldName , depth );
104
123
break ;
105
124
} else if (this .parser .currentToken () == Token .END_ARRAY ) {
106
125
// skip
107
126
} else if (this .parser .currentToken () == Token .START_OBJECT ) {
108
- parseToken (path , currentFieldName );
127
+ parseToken (path , currentFieldName , depth + 1 );
109
128
int dotIndex = path .lastIndexOf (DOT_SYMBOL , path .length ());
110
129
111
130
if (dotIndex != -1 && path .length () > currentFieldName .length ()) {
@@ -115,9 +134,10 @@ private void parseToken(StringBuilder path, String currentFieldName) throws IOEx
115
134
if (!path .toString ().contains (currentFieldName )) {
116
135
path .append (DOT_SYMBOL ).append (currentFieldName );
117
136
}
118
- parseValue (parsedFields );
119
- this .valueList .add (parsedFields .toString ());
120
- this .valueAndPathList .add (path + EQUAL_SYMBOL + parsedFields );
137
+ if (parseValue (parsedFields )) {
138
+ this .valueList .add (parsedFields .toString ());
139
+ this .valueAndPathList .add (path + EQUAL_SYMBOL + parsedFields );
140
+ }
121
141
int dotIndex = path .lastIndexOf (DOT_SYMBOL , path .length ());
122
142
if (dotIndex != -1 && path .length () > currentFieldName .length ()) {
123
143
path .setLength (path .length () - currentFieldName .length () - 1 );
@@ -127,13 +147,35 @@ private void parseToken(StringBuilder path, String currentFieldName) throws IOEx
127
147
}
128
148
}
129
149
130
- private void parseValue (StringBuilder parsedFields ) throws IOException {
150
+ private boolean processNoNestedValue () throws IOException {
151
+ if (parser .currentToken () == Token .VALUE_NULL ) {
152
+ if (nullValue != null ) {
153
+ this .valueList .add (nullValue );
154
+ }
155
+ return true ;
156
+ } else if (this .parser .currentToken () == Token .VALUE_STRING
157
+ || this .parser .currentToken () == Token .VALUE_NUMBER
158
+ || this .parser .currentToken () == Token .VALUE_BOOLEAN ) {
159
+ String value = this .parser .textOrNull ();
160
+ if (value != null && value .length () <= ignoreAbove ) {
161
+ this .valueList .add (value );
162
+ }
163
+ return true ;
164
+ }
165
+ return false ;
166
+ }
167
+
168
+ private boolean parseValue (StringBuilder parsedFields ) throws IOException {
131
169
switch (this .parser .currentToken ()) {
132
170
case VALUE_BOOLEAN :
133
171
case VALUE_NUMBER :
134
172
case VALUE_STRING :
135
173
case VALUE_NULL :
136
- parsedFields .append (this .parser .textOrNull ());
174
+ String value = this .parser .textOrNull ();
175
+ if (value != null && value .length () <= ignoreAbove ) {
176
+ parsedFields .append (value );
177
+ return true ;
178
+ }
137
179
break ;
138
180
// Handle other token types as needed
139
181
case FIELD_NAME :
@@ -144,6 +186,7 @@ private void parseValue(StringBuilder parsedFields) throws IOException {
144
186
default :
145
187
throw new IOException ("Unsupported token type [" + parser .currentToken () + "]" );
146
188
}
189
+ return false ;
147
190
}
148
191
149
192
@ Override
0 commit comments