1919import com .google .protobuf .Descriptors .FieldDescriptor ;
2020import com .google .protobuf .DynamicMessage ;
2121import com .google .protobuf .Message ;
22+ import java .util .HashMap ;
2223import java .util .List ;
2324import org .json .JSONArray ;
2425import org .json .JSONException ;
@@ -77,15 +78,21 @@ private static DynamicMessage convertJsonToProtoMessageImpl(
7778 if (JSONObject .getNames (json ).length > protoFields .size ()) {
7879 if (!allowUnknownFields ) {
7980 throw new IllegalArgumentException (
80- "JSONObject has unknown fields . Set allowUnknownFields to True to ignore unknown fields." );
81+ "JSONObject has fields unknown to BigQuery: f1 . Set allowUnknownFields to True to allow unknown fields." );
8182 }
8283 }
84+ HashMap <String , String > jsonLowercaseNameToActualName = new HashMap <String , String >();
85+ String [] actualNames = JSONObject .getNames (json );
86+ for (int i = 0 ; i < actualNames .length ; i ++) {
87+ jsonLowercaseNameToActualName .put (actualNames [i ].toLowerCase (), actualNames [i ]);
88+ }
8389
8490 for (FieldDescriptor field : protoFields ) {
8591 String fieldName = field .getName ();
92+ String lowercaseFieldName = fieldName .toLowerCase ();
8693 String currentScope = jsonScope + "." + fieldName ;
8794
88- if (!json . has ( fieldName )) {
95+ if (!jsonLowercaseNameToActualName . containsKey ( lowercaseFieldName )) {
8996 if (field .isRequired ()) {
9097 throw new IllegalArgumentException (
9198 "JSONObject does not have the required field " + currentScope + "." );
@@ -95,9 +102,21 @@ private static DynamicMessage convertJsonToProtoMessageImpl(
95102 }
96103 matchedFields ++;
97104 if (!field .isRepeated ()) {
98- fillField (protoMsg , field , json , currentScope , allowUnknownFields );
105+ fillField (
106+ protoMsg ,
107+ field ,
108+ json ,
109+ jsonLowercaseNameToActualName .get (lowercaseFieldName ),
110+ currentScope ,
111+ allowUnknownFields );
99112 } else {
100- fillRepeatedField (protoMsg , field , json , currentScope , allowUnknownFields );
113+ fillRepeatedField (
114+ protoMsg ,
115+ field ,
116+ json ,
117+ jsonLowercaseNameToActualName .get (lowercaseFieldName ),
118+ currentScope ,
119+ allowUnknownFields );
101120 }
102121 }
103122 if (matchedFields == 0 && topLevel ) {
@@ -110,50 +129,51 @@ private static DynamicMessage convertJsonToProtoMessageImpl(
110129 /**
111130 * Fills a non-repetaed protoField with the json data.
112131 *
113- * @param protoMsg
114- * @param field
132+ * @param protoMsg The protocol buffer message being constructed
133+ * @param fieldDescriptor
115134 * @param json
135+ * @param actualJsonKeyName Actual key name in JSONObject instead of lowercased version
116136 * @param currentScope Debugging purposes
117137 * @param allowUnknownFields Ignores unknown JSON fields.
118138 * @throws IllegalArgumentException when JSON data is not compatible with proto descriptor.
119139 */
120140 private static void fillField (
121141 DynamicMessage .Builder protoMsg ,
122- FieldDescriptor field ,
142+ FieldDescriptor fieldDescriptor ,
123143 JSONObject json ,
144+ String actualJsonKeyName ,
124145 String currentScope ,
125146 boolean allowUnknownFields )
126147 throws IllegalArgumentException {
127148
128- String fieldName = field .getName ();
129- switch (field .getType ()) {
149+ switch (fieldDescriptor .getType ()) {
130150 case BOOL :
131151 try {
132- protoMsg .setField (field , new Boolean (json .getBoolean (fieldName )));
152+ protoMsg .setField (fieldDescriptor , new Boolean (json .getBoolean (actualJsonKeyName )));
133153 } catch (JSONException e ) {
134154 throw new IllegalArgumentException (
135155 "JSONObject does not have a boolean field at " + currentScope + "." );
136156 }
137157 break ;
138158 case BYTES :
139159 try {
140- protoMsg .setField (field , json .getString (fieldName ).getBytes ());
160+ protoMsg .setField (fieldDescriptor , json .getString (actualJsonKeyName ).getBytes ());
141161 } catch (JSONException e ) {
142162 throw new IllegalArgumentException (
143163 "JSONObject does not have a string field at " + currentScope + "." );
144164 }
145165 break ;
146166 case INT64 :
147167 try {
148- java .lang .Object val = json .get (fieldName );
168+ java .lang .Object val = json .get (actualJsonKeyName );
149169 if (val instanceof Byte ) {
150- protoMsg .setField (field , new Long ((Byte ) val ));
170+ protoMsg .setField (fieldDescriptor , new Long ((Byte ) val ));
151171 } else if (val instanceof Short ) {
152- protoMsg .setField (field , new Long ((Short ) val ));
172+ protoMsg .setField (fieldDescriptor , new Long ((Short ) val ));
153173 } else if (val instanceof Integer ) {
154- protoMsg .setField (field , new Long ((Integer ) val ));
174+ protoMsg .setField (fieldDescriptor , new Long ((Integer ) val ));
155175 } else if (val instanceof Long ) {
156- protoMsg .setField (field , new Long ((Long ) val ));
176+ protoMsg .setField (fieldDescriptor , new Long ((Long ) val ));
157177 } else {
158178 throw new IllegalArgumentException (
159179 "JSONObject does not have a int64 field at " + currentScope + "." );
@@ -163,21 +183,39 @@ private static void fillField(
163183 "JSONObject does not have a int64 field at " + currentScope + "." );
164184 }
165185 break ;
186+ case INT32 :
187+ try {
188+ java .lang .Object val = json .get (actualJsonKeyName );
189+ if (val instanceof Byte ) {
190+ protoMsg .setField (fieldDescriptor , new Integer ((Byte ) val ));
191+ } else if (val instanceof Short ) {
192+ protoMsg .setField (fieldDescriptor , new Integer ((Short ) val ));
193+ } else if (val instanceof Integer ) {
194+ protoMsg .setField (fieldDescriptor , new Integer ((Integer ) val ));
195+ } else {
196+ throw new IllegalArgumentException (
197+ "JSONObject does not have a int32 field at " + currentScope + "." );
198+ }
199+ } catch (JSONException e ) {
200+ throw new IllegalArgumentException (
201+ "JSONObject does not have a int32 field at " + currentScope + "." );
202+ }
203+ break ;
166204 case STRING :
167205 try {
168- protoMsg .setField (field , json .getString (fieldName ));
206+ protoMsg .setField (fieldDescriptor , json .getString (actualJsonKeyName ));
169207 } catch (JSONException e ) {
170208 throw new IllegalArgumentException (
171209 "JSONObject does not have a string field at " + currentScope + "." );
172210 }
173211 break ;
174212 case DOUBLE :
175213 try {
176- java .lang .Object val = json .get (fieldName );
214+ java .lang .Object val = json .get (actualJsonKeyName );
177215 if (val instanceof Double ) {
178- protoMsg .setField (field , new Double ((double ) val ));
216+ protoMsg .setField (fieldDescriptor , new Double ((double ) val ));
179217 } else if (val instanceof Float ) {
180- protoMsg .setField (field , new Double ((float ) val ));
218+ protoMsg .setField (fieldDescriptor , new Double ((float ) val ));
181219 } else {
182220 throw new IllegalArgumentException (
183221 "JSONObject does not have a double field at " + currentScope + "." );
@@ -188,13 +226,13 @@ private static void fillField(
188226 }
189227 break ;
190228 case MESSAGE :
191- Message .Builder message = protoMsg .newBuilderForField (field );
229+ Message .Builder message = protoMsg .newBuilderForField (fieldDescriptor );
192230 try {
193231 protoMsg .setField (
194- field ,
232+ fieldDescriptor ,
195233 convertJsonToProtoMessageImpl (
196- field .getMessageType (),
197- json .getJSONObject (fieldName ),
234+ fieldDescriptor .getMessageType (),
235+ json .getJSONObject (actualJsonKeyName ),
198236 currentScope ,
199237 false ,
200238 allowUnknownFields ));
@@ -209,34 +247,36 @@ private static void fillField(
209247 /**
210248 * Fills a repeated protoField with the json data.
211249 *
212- * @param protoMsg
213- * @param field
250+ * @param protoMsg The protocol buffer message being constructed
251+ * @param fieldDescriptor
214252 * @param json If root level has no matching fields, throws exception.
253+ * @param actualJsonKeyName Actual key name in JSONObject instead of lowercased version
215254 * @param currentScope Debugging purposes
216255 * @param allowUnknownFields Ignores unknown JSON fields.
217256 * @throws IllegalArgumentException when JSON data is not compatible with proto descriptor.
218257 */
219258 private static void fillRepeatedField (
220259 DynamicMessage .Builder protoMsg ,
221- FieldDescriptor field ,
260+ FieldDescriptor fieldDescriptor ,
222261 JSONObject json ,
262+ String actualJsonKeyName ,
223263 String currentScope ,
224264 boolean allowUnknownFields )
225265 throws IllegalArgumentException {
226- String fieldName = field . getName ();
266+
227267 JSONArray jsonArray ;
228268 try {
229- jsonArray = json .getJSONArray (fieldName );
269+ jsonArray = json .getJSONArray (actualJsonKeyName );
230270 } catch (JSONException e ) {
231271 throw new IllegalArgumentException (
232272 "JSONObject does not have a array field at " + currentScope + "." );
233273 }
234274
235- switch (field .getType ()) {
275+ switch (fieldDescriptor .getType ()) {
236276 case BOOL :
237277 for (int i = 0 ; i < jsonArray .length (); i ++) {
238278 try {
239- protoMsg .addRepeatedField (field , new Boolean (jsonArray .getBoolean (i )));
279+ protoMsg .addRepeatedField (fieldDescriptor , new Boolean (jsonArray .getBoolean (i )));
240280 } catch (JSONException e ) {
241281 throw new IllegalArgumentException (
242282 "JSONObject does not have a boolean field at "
@@ -251,7 +291,7 @@ private static void fillRepeatedField(
251291 case BYTES :
252292 for (int i = 0 ; i < jsonArray .length (); i ++) {
253293 try {
254- protoMsg .addRepeatedField (field , jsonArray .getString (i ).getBytes ());
294+ protoMsg .addRepeatedField (fieldDescriptor , jsonArray .getString (i ).getBytes ());
255295 } catch (JSONException e ) {
256296 throw new IllegalArgumentException (
257297 "JSONObject does not have a string field at " + currentScope + "[" + i + "]" + "." );
@@ -263,13 +303,13 @@ private static void fillRepeatedField(
263303 try {
264304 java .lang .Object val = jsonArray .get (i );
265305 if (val instanceof Byte ) {
266- protoMsg .addRepeatedField (field , new Long ((Byte ) val ));
306+ protoMsg .addRepeatedField (fieldDescriptor , new Long ((Byte ) val ));
267307 } else if (val instanceof Short ) {
268- protoMsg .addRepeatedField (field , new Long ((Short ) val ));
308+ protoMsg .addRepeatedField (fieldDescriptor , new Long ((Short ) val ));
269309 } else if (val instanceof Integer ) {
270- protoMsg .addRepeatedField (field , new Long ((Integer ) val ));
310+ protoMsg .addRepeatedField (fieldDescriptor , new Long ((Integer ) val ));
271311 } else if (val instanceof Long ) {
272- protoMsg .addRepeatedField (field , new Long ((Long ) val ));
312+ protoMsg .addRepeatedField (fieldDescriptor , new Long ((Long ) val ));
273313 } else {
274314 throw new IllegalArgumentException (
275315 "JSONObject does not have a int64 field at "
@@ -285,10 +325,35 @@ private static void fillRepeatedField(
285325 }
286326 }
287327 break ;
328+ case INT32 :
329+ for (int i = 0 ; i < jsonArray .length (); i ++) {
330+ try {
331+ java .lang .Object val = jsonArray .get (i );
332+ if (val instanceof Byte ) {
333+ protoMsg .addRepeatedField (fieldDescriptor , new Integer ((Byte ) val ));
334+ } else if (val instanceof Short ) {
335+ protoMsg .addRepeatedField (fieldDescriptor , new Integer ((Short ) val ));
336+ } else if (val instanceof Integer ) {
337+ protoMsg .addRepeatedField (fieldDescriptor , new Integer ((Integer ) val ));
338+ } else {
339+ throw new IllegalArgumentException (
340+ "JSONObject does not have a int32 field at "
341+ + currentScope
342+ + "["
343+ + i
344+ + "]"
345+ + "." );
346+ }
347+ } catch (JSONException e ) {
348+ throw new IllegalArgumentException (
349+ "JSONObject does not have a int32 field at " + currentScope + "[" + i + "]" + "." );
350+ }
351+ }
352+ break ;
288353 case STRING :
289354 for (int i = 0 ; i < jsonArray .length (); i ++) {
290355 try {
291- protoMsg .addRepeatedField (field , jsonArray .getString (i ));
356+ protoMsg .addRepeatedField (fieldDescriptor , jsonArray .getString (i ));
292357 } catch (JSONException e ) {
293358 throw new IllegalArgumentException (
294359 "JSONObject does not have a string field at " + currentScope + "[" + i + "]" + "." );
@@ -300,9 +365,9 @@ private static void fillRepeatedField(
300365 try {
301366 java .lang .Object val = jsonArray .get (i );
302367 if (val instanceof Double ) {
303- protoMsg .addRepeatedField (field , new Double ((double ) val ));
368+ protoMsg .addRepeatedField (fieldDescriptor , new Double ((double ) val ));
304369 } else if (val instanceof Float ) {
305- protoMsg .addRepeatedField (field , new Double ((float ) val ));
370+ protoMsg .addRepeatedField (fieldDescriptor , new Double ((float ) val ));
306371 } else {
307372 throw new IllegalArgumentException (
308373 "JSONObject does not have a double field at "
@@ -321,11 +386,11 @@ private static void fillRepeatedField(
321386 case MESSAGE :
322387 for (int i = 0 ; i < jsonArray .length (); i ++) {
323388 try {
324- Message .Builder message = protoMsg .newBuilderForField (field );
389+ Message .Builder message = protoMsg .newBuilderForField (fieldDescriptor );
325390 protoMsg .addRepeatedField (
326- field ,
391+ fieldDescriptor ,
327392 convertJsonToProtoMessageImpl (
328- field .getMessageType (),
393+ fieldDescriptor .getMessageType (),
329394 jsonArray .getJSONObject (i ),
330395 currentScope ,
331396 false ,
0 commit comments