@@ -1378,63 +1378,88 @@ public JsonGenerator writeTypeId(Object id) throws JacksonException {
1378
1378
public WritableTypeId writeTypePrefix (WritableTypeId typeIdDef )
1379
1379
throws JacksonException
1380
1380
{
1381
- Object id = typeIdDef .id ;
1382
-
1383
- final JsonToken valueShape = typeIdDef .valueShape ;
1384
- if (canWriteTypeId ()) {
1385
- typeIdDef .wrapperWritten = false ;
1386
- // just rely on native type output method (sub-classes likely to override)
1387
- writeTypeId (id );
1388
- } else {
1389
- // No native type id; write wrappers
1390
- // Normally we only support String type ids (non-String reserved for native type ids)
1391
- String idStr = (id instanceof String ) ? (String ) id : String .valueOf (id );
1392
- typeIdDef .wrapperWritten = true ;
1393
-
1394
- Inclusion incl = typeIdDef .include ;
1395
- // first: can not output "as property" if value not Object; if so, must do "as array"
1396
- if ((valueShape != JsonToken .START_OBJECT )
1397
- && incl .requiresObjectContext ()) {
1398
- typeIdDef .include = incl = WritableTypeId .Inclusion .WRAPPER_ARRAY ;
1381
+ final boolean wasStartObjectWritten = canWriteTypeId ()
1382
+ ? _writeTypePrefixUsingNative (typeIdDef )
1383
+ : _writeTypePrefixUsingWrapper (typeIdDef );
1384
+
1385
+ // And then possible start marker for value itself:
1386
+ switch (typeIdDef .valueShape ) {
1387
+ case START_OBJECT :
1388
+ if (!wasStartObjectWritten ) {
1389
+ writeStartObject (typeIdDef .forValue );
1399
1390
}
1391
+ break ;
1392
+ case START_ARRAY :
1393
+ writeStartArray (typeIdDef .forValue );
1394
+ break ;
1395
+ default : // otherwise: no start marker
1396
+ }
1400
1397
1401
- switch (incl ) {
1402
- case PARENT_PROPERTY :
1403
- // nothing to do here, as it has to be written in suffix...
1404
- break ;
1405
- case PAYLOAD_PROPERTY :
1406
- // only output as native type id; otherwise caller must handle using some
1407
- // other mechanism, so...
1408
- break ;
1409
- case METADATA_PROPERTY :
1410
- // must have Object context by now, so simply write as property name
1411
- // Note, too, that it's bit tricky, since we must print START_OBJECT that is part
1412
- // of value first -- and then NOT output it later on: hence return "early"
1413
- writeStartObject (typeIdDef .forValue );
1414
- writeStringProperty (typeIdDef .asProperty , idStr );
1415
- return typeIdDef ;
1398
+ return typeIdDef ;
1399
+ }
1416
1400
1417
- case WRAPPER_OBJECT :
1418
- // NOTE: this is wrapper, not directly related to value to output, so don't pass
1419
- writeStartObject ();
1420
- writeName (idStr );
1421
- break ;
1422
- case WRAPPER_ARRAY :
1423
- default : // should never occur but translate as "as-array"
1424
- writeStartArray (); // wrapper, not actual array object to write
1425
- writeString (idStr );
1426
- }
1401
+ /**
1402
+ * Writes a native type id (when supported by format).
1403
+ *
1404
+ * @return True if start of an object has been written, False otherwise.
1405
+ */
1406
+ protected boolean _writeTypePrefixUsingNative (WritableTypeId typeIdDef ) throws JacksonException {
1407
+ typeIdDef .wrapperWritten = false ;
1408
+ writeTypeId (typeIdDef .id );
1409
+ return false ;
1410
+ }
1411
+
1412
+ /**
1413
+ * Writes a wrapper for the type id if necessary.
1414
+ *
1415
+ * @return True if start of an object has been written, false otherwise.
1416
+ */
1417
+ protected boolean _writeTypePrefixUsingWrapper (WritableTypeId typeIdDef ) throws JacksonException {
1418
+ // Normally we only support String type ids (non-String reserved for native type ids)
1419
+ final String id = Objects .toString (typeIdDef .id , null );
1420
+
1421
+ // If we don't have Type ID we don't write a wrapper.
1422
+ if (id == null ) {
1423
+ return false ;
1427
1424
}
1428
- // and finally possible start marker for value itself:
1429
- if (valueShape == JsonToken .START_OBJECT ) {
1425
+ Inclusion incl = typeIdDef .include ;
1426
+
1427
+ // first: can not output "as property" if value not Object; if so, must do "as array"
1428
+ if ((typeIdDef .valueShape != JsonToken .START_OBJECT ) && incl .requiresObjectContext ()) {
1429
+ typeIdDef .include = incl = WritableTypeId .Inclusion .WRAPPER_ARRAY ;
1430
+ }
1431
+
1432
+ typeIdDef .wrapperWritten = true ;
1433
+ switch (incl ) {
1434
+ case PARENT_PROPERTY :
1435
+ // nothing to do here, as it has to be written in suffix...
1436
+ break ;
1437
+ case PAYLOAD_PROPERTY :
1438
+ // only output as native type id; otherwise caller must handle using some
1439
+ // other mechanism, so...
1440
+ break ;
1441
+ case METADATA_PROPERTY :
1442
+ // must have Object context by now, so simply write as field name
1443
+ // Note, too, that it's bit tricky, since we must print START_OBJECT that is part
1444
+ // of value first -- and then NOT output it later on: hence return "early"
1430
1445
writeStartObject (typeIdDef .forValue );
1431
- } else if (valueShape == JsonToken .START_ARRAY ) {
1432
- // should we now set the current object?
1433
- writeStartArray ();
1446
+ writeStringProperty (typeIdDef .asProperty , id );
1447
+ return true ;
1448
+
1449
+ case WRAPPER_OBJECT :
1450
+ // NOTE: this is wrapper, not directly related to value to output, so
1451
+ // do NOT pass "typeIdDef.forValue"
1452
+ writeStartObject ();
1453
+ writeName (id );
1454
+ break ;
1455
+ case WRAPPER_ARRAY :
1456
+ default : // should never occur but translate as "as-array"
1457
+ writeStartArray (); // wrapper, not actual array object to write
1458
+ writeString (id );
1434
1459
}
1435
- return typeIdDef ;
1460
+ return false ;
1436
1461
}
1437
-
1462
+
1438
1463
public WritableTypeId writeTypeSuffix (WritableTypeId typeIdDef ) throws JacksonException
1439
1464
{
1440
1465
final JsonToken valueShape = typeIdDef .valueShape ;
0 commit comments