Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual merge of #1356 from 2.19 to master (merge conflicts) #1357

Merged
merged 1 commit into from
Nov 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 75 additions & 50 deletions src/main/java/tools/jackson/core/JsonGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1378,63 +1378,88 @@ public JsonGenerator writeTypeId(Object id) throws JacksonException {
public WritableTypeId writeTypePrefix(WritableTypeId typeIdDef)
throws JacksonException
{
Object id = typeIdDef.id;

final JsonToken valueShape = typeIdDef.valueShape;
if (canWriteTypeId()) {
typeIdDef.wrapperWritten = false;
// just rely on native type output method (sub-classes likely to override)
writeTypeId(id);
} else {
// No native type id; write wrappers
// Normally we only support String type ids (non-String reserved for native type ids)
String idStr = (id instanceof String) ? (String) id : String.valueOf(id);
typeIdDef.wrapperWritten = true;

Inclusion incl = typeIdDef.include;
// first: can not output "as property" if value not Object; if so, must do "as array"
if ((valueShape != JsonToken.START_OBJECT)
&& incl.requiresObjectContext()) {
typeIdDef.include = incl = WritableTypeId.Inclusion.WRAPPER_ARRAY;
final boolean wasStartObjectWritten = canWriteTypeId()
? _writeTypePrefixUsingNative(typeIdDef)
: _writeTypePrefixUsingWrapper(typeIdDef);

// And then possible start marker for value itself:
switch (typeIdDef.valueShape) {
case START_OBJECT:
if (!wasStartObjectWritten) {
writeStartObject(typeIdDef.forValue);
}
break;
case START_ARRAY:
writeStartArray(typeIdDef.forValue);
break;
default: // otherwise: no start marker
}

switch (incl) {
case PARENT_PROPERTY:
// nothing to do here, as it has to be written in suffix...
break;
case PAYLOAD_PROPERTY:
// only output as native type id; otherwise caller must handle using some
// other mechanism, so...
break;
case METADATA_PROPERTY:
// must have Object context by now, so simply write as property name
// Note, too, that it's bit tricky, since we must print START_OBJECT that is part
// of value first -- and then NOT output it later on: hence return "early"
writeStartObject(typeIdDef.forValue);
writeStringProperty(typeIdDef.asProperty, idStr);
return typeIdDef;
return typeIdDef;
}

case WRAPPER_OBJECT:
// NOTE: this is wrapper, not directly related to value to output, so don't pass
writeStartObject();
writeName(idStr);
break;
case WRAPPER_ARRAY:
default: // should never occur but translate as "as-array"
writeStartArray(); // wrapper, not actual array object to write
writeString(idStr);
}
/**
* Writes a native type id (when supported by format).
*
* @return True if start of an object has been written, False otherwise.
*/
protected boolean _writeTypePrefixUsingNative(WritableTypeId typeIdDef) throws JacksonException {
typeIdDef.wrapperWritten = false;
writeTypeId(typeIdDef.id);
return false;
}

/**
* Writes a wrapper for the type id if necessary.
*
* @return True if start of an object has been written, false otherwise.
*/
protected boolean _writeTypePrefixUsingWrapper(WritableTypeId typeIdDef) throws JacksonException {
// Normally we only support String type ids (non-String reserved for native type ids)
final String id = Objects.toString(typeIdDef.id, null);

// If we don't have Type ID we don't write a wrapper.
if (id == null) {
return false;
}
// and finally possible start marker for value itself:
if (valueShape == JsonToken.START_OBJECT) {
Inclusion incl = typeIdDef.include;

// first: can not output "as property" if value not Object; if so, must do "as array"
if ((typeIdDef.valueShape != JsonToken.START_OBJECT) && incl.requiresObjectContext()) {
typeIdDef.include = incl = WritableTypeId.Inclusion.WRAPPER_ARRAY;
}

typeIdDef.wrapperWritten = true;
switch (incl) {
case PARENT_PROPERTY:
// nothing to do here, as it has to be written in suffix...
break;
case PAYLOAD_PROPERTY:
// only output as native type id; otherwise caller must handle using some
// other mechanism, so...
break;
case METADATA_PROPERTY:
// must have Object context by now, so simply write as field name
// Note, too, that it's bit tricky, since we must print START_OBJECT that is part
// of value first -- and then NOT output it later on: hence return "early"
writeStartObject(typeIdDef.forValue);
} else if (valueShape == JsonToken.START_ARRAY) {
// should we now set the current object?
writeStartArray();
writeStringProperty(typeIdDef.asProperty, id);
return true;

case WRAPPER_OBJECT:
// NOTE: this is wrapper, not directly related to value to output, so
// do NOT pass "typeIdDef.forValue"
writeStartObject();
writeName(id);
break;
case WRAPPER_ARRAY:
default: // should never occur but translate as "as-array"
writeStartArray(); // wrapper, not actual array object to write
writeString(id);
}
return typeIdDef;
return false;
}

public WritableTypeId writeTypeSuffix(WritableTypeId typeIdDef) throws JacksonException
{
final JsonToken valueShape = typeIdDef.valueShape;
Expand Down