Skip to content
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,13 @@ public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
* @param schema Schema
*/
protected void normalizeReferenceSchema(Schema schema) {
if (schema.getType() != null || schema.getTypes() != null && !schema.getTypes().isEmpty()) {
// clears type(s) given that $ref is set
schema.setType(null);
schema.setTypes(null);
LOGGER.warn("Type(s) cleared (set to null) given $ref is set to {}.", schema.get$ref());
}

if (schema.getTitle() != null || schema.getDescription() != null
|| schema.getNullable() != null || schema.getDefault() != null || schema.getDeprecated() != null
|| schema.getMaximum() != null || schema.getMinimum() != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1117,3 +1117,11 @@ components:
properties:
dummy:
type: string
PetWithTypesObjectNullAndRef:
type: object
properties:
first_property:
type:
- "object"
- "null"
$ref: '#/components/schemas/Pet'
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ docs/OneOfStringOrInt.md
docs/Order.md
docs/Pet.md
docs/PetApi.md
docs/PetWithTypesObjectNullAndRef.md
docs/RefRefToPathLevelParameterOneofRefToOneofParameter.md
docs/RefToRefParameterAnyofRefToAnyofParameter.md
docs/SelfReferenceAdditionalProperties.md
Expand Down Expand Up @@ -89,6 +90,7 @@ src/main/java/org/openapitools/client/model/ModelApiResponse.java
src/main/java/org/openapitools/client/model/OneOfStringOrInt.java
src/main/java/org/openapitools/client/model/Order.java
src/main/java/org/openapitools/client/model/Pet.java
src/main/java/org/openapitools/client/model/PetWithTypesObjectNullAndRef.java
src/main/java/org/openapitools/client/model/RefRefToPathLevelParameterOneofRefToOneofParameter.java
src/main/java/org/openapitools/client/model/RefToRefParameterAnyofRefToAnyofParameter.java
src/main/java/org/openapitools/client/model/SelfReferenceAdditionalProperties.java
Expand Down
1 change: 1 addition & 0 deletions samples/client/petstore/java/okhttp-gson-3.1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ Class | Method | HTTP request | Description
- [OneOfStringOrInt](docs/OneOfStringOrInt.md)
- [Order](docs/Order.md)
- [Pet](docs/Pet.md)
- [PetWithTypesObjectNullAndRef](docs/PetWithTypesObjectNullAndRef.md)
- [RefRefToPathLevelParameterOneofRefToOneofParameter](docs/RefRefToPathLevelParameterOneofRefToOneofParameter.md)
- [RefToRefParameterAnyofRefToAnyofParameter](docs/RefToRefParameterAnyofRefToAnyofParameter.md)
- [SelfReferenceAdditionalProperties](docs/SelfReferenceAdditionalProperties.md)
Expand Down
4 changes: 4 additions & 0 deletions samples/client/petstore/java/okhttp-gson-3.1/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,10 @@ components:
properties:
dummy:
type: string
PetWithTypesObjectNullAndRef:
properties:
first_property:
$ref: "#/components/schemas/Pet"
updatePetWithForm_request:
properties:
name:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@


# PetWithTypesObjectNullAndRef


## Properties

| Name | Type | Description | Notes |
|------------ | ------------- | ------------- | -------------|
|**firstProperty** | [**Pet**](Pet.md) | | [optional] |



Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, Stri
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.OneOfStringOrInt.CustomTypeAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Order.CustomTypeAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Pet.CustomTypeAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.PetWithTypesObjectNullAndRef.CustomTypeAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.RefRefToPathLevelParameterOneofRefToOneofParameter.CustomTypeAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.RefToRefParameterAnyofRefToAnyofParameter.CustomTypeAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.SelfReferenceAdditionalProperties.CustomTypeAdapterFactory());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
/*
* OpenAPI Petstore
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
*
* The version of the OpenAPI document: 1.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/


package org.openapitools.client.model;

import java.util.Objects;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.Arrays;
import org.openapitools.client.model.Pet;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.openapitools.client.JSON;

/**
* PetWithTypesObjectNullAndRef
*/
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.20.0-SNAPSHOT")
public class PetWithTypesObjectNullAndRef {
public static final String SERIALIZED_NAME_FIRST_PROPERTY = "first_property";
@SerializedName(SERIALIZED_NAME_FIRST_PROPERTY)
@javax.annotation.Nullable
private Pet firstProperty;

public PetWithTypesObjectNullAndRef() {
}

public PetWithTypesObjectNullAndRef firstProperty(@javax.annotation.Nullable Pet firstProperty) {
this.firstProperty = firstProperty;
return this;
}

/**
* Get firstProperty
* @return firstProperty
*/
@javax.annotation.Nullable
public Pet getFirstProperty() {
return firstProperty;
}

public void setFirstProperty(@javax.annotation.Nullable Pet firstProperty) {
this.firstProperty = firstProperty;
}

/**
* A container for additional, undeclared properties.
* This is a holder for any undeclared properties as specified with
* the 'additionalProperties' keyword in the OAS document.
*/
private Map<String, Object> additionalProperties;

/**
* Set the additional (undeclared) property with the specified name and value.
* If the property does not already exist, create it otherwise replace it.
*
* @param key name of the property
* @param value value of the property
* @return the PetWithTypesObjectNullAndRef instance itself
*/
public PetWithTypesObjectNullAndRef putAdditionalProperty(String key, Object value) {
if (this.additionalProperties == null) {
this.additionalProperties = new HashMap<String, Object>();
}
this.additionalProperties.put(key, value);
return this;
}

/**
* Return the additional (undeclared) property.
*
* @return a map of objects
*/
public Map<String, Object> getAdditionalProperties() {
return additionalProperties;
}

/**
* Return the additional (undeclared) property with the specified name.
*
* @param key name of the property
* @return an object
*/
public Object getAdditionalProperty(String key) {
if (this.additionalProperties == null) {
return null;
}
return this.additionalProperties.get(key);
}


@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
PetWithTypesObjectNullAndRef petWithTypesObjectNullAndRef = (PetWithTypesObjectNullAndRef) o;
return Objects.equals(this.firstProperty, petWithTypesObjectNullAndRef.firstProperty)&&
Objects.equals(this.additionalProperties, petWithTypesObjectNullAndRef.additionalProperties);
}

@Override
public int hashCode() {
return Objects.hash(firstProperty, additionalProperties);
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class PetWithTypesObjectNullAndRef {\n");
sb.append(" firstProperty: ").append(toIndentedString(firstProperty)).append("\n");
sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n");
sb.append("}");
return sb.toString();
}

/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}


public static HashSet<String> openapiFields;
public static HashSet<String> openapiRequiredFields;

static {
// a set of all properties/fields (JSON key names)
openapiFields = new HashSet<String>(Arrays.asList("first_property"));

// a set of required properties/fields (JSON key names)
openapiRequiredFields = new HashSet<String>(0);
}

/**
* Validates the JSON Element and throws an exception if issues found
*
* @param jsonElement JSON Element
* @throws IOException if the JSON Element is invalid with respect to PetWithTypesObjectNullAndRef
*/
public static void validateJsonElement(JsonElement jsonElement) throws IOException {
if (jsonElement == null) {
if (!PetWithTypesObjectNullAndRef.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null
throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field(s) %s in PetWithTypesObjectNullAndRef is not found in the empty JSON string", PetWithTypesObjectNullAndRef.openapiRequiredFields.toString()));
}
}
JsonObject jsonObj = jsonElement.getAsJsonObject();
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Guard against null before calling getAsJsonObject(); otherwise valid null JSON triggers a NullPointerException when no required fields are present.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-gson-3.1/src/main/java/org/openapitools/client/model/PetWithTypesObjectNullAndRef.java, line 189:

<comment>Guard against null before calling getAsJsonObject(); otherwise valid null JSON triggers a NullPointerException when no required fields are present.</comment>

<file context>
@@ -0,0 +1,288 @@
+          throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field(s) %s in PetWithTypesObjectNullAndRef is not found in the empty JSON string", PetWithTypesObjectNullAndRef.openapiRequiredFields.toString()));
+        }
+      }
+        JsonObject jsonObj = jsonElement.getAsJsonObject();
+      // validate the optional field `first_property`
+      if (jsonObj.get("first_property") != null && !jsonObj.get("first_property").isJsonNull()) {
</file context>
Fix with Cubic

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not related to this PR

we can file another PR in the future to have better guard against NPE in this code block

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying—understood this is out of scope for this PR.

// validate the optional field `first_property`
if (jsonObj.get("first_property") != null && !jsonObj.get("first_property").isJsonNull()) {
Pet.validateJsonElement(jsonObj.get("first_property"));
}
}

public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
@SuppressWarnings("unchecked")
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (!PetWithTypesObjectNullAndRef.class.isAssignableFrom(type.getRawType())) {
return null; // this class only serializes 'PetWithTypesObjectNullAndRef' and its subtypes
}
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
final TypeAdapter<PetWithTypesObjectNullAndRef> thisAdapter
= gson.getDelegateAdapter(this, TypeToken.get(PetWithTypesObjectNullAndRef.class));

return (TypeAdapter<T>) new TypeAdapter<PetWithTypesObjectNullAndRef>() {
@Override
public void write(JsonWriter out, PetWithTypesObjectNullAndRef value) throws IOException {
JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject();
obj.remove("additionalProperties");
// serialize additional properties
if (value.getAdditionalProperties() != null) {
for (Map.Entry<String, Object> entry : value.getAdditionalProperties().entrySet()) {
if (entry.getValue() instanceof String)
obj.addProperty(entry.getKey(), (String) entry.getValue());
else if (entry.getValue() instanceof Number)
obj.addProperty(entry.getKey(), (Number) entry.getValue());
else if (entry.getValue() instanceof Boolean)
obj.addProperty(entry.getKey(), (Boolean) entry.getValue());
else if (entry.getValue() instanceof Character)
obj.addProperty(entry.getKey(), (Character) entry.getValue());
else {
JsonElement jsonElement = gson.toJsonTree(entry.getValue());
if (jsonElement.isJsonArray()) {
obj.add(entry.getKey(), jsonElement.getAsJsonArray());
} else {
obj.add(entry.getKey(), jsonElement.getAsJsonObject());
}
}
}
}
elementAdapter.write(out, obj);
}

@Override
public PetWithTypesObjectNullAndRef read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
validateJsonElement(jsonElement);
JsonObject jsonObj = jsonElement.getAsJsonObject();
// store additional fields in the deserialized instance
PetWithTypesObjectNullAndRef instance = thisAdapter.fromJsonTree(jsonObj);
for (Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) {
if (!openapiFields.contains(entry.getKey())) {
if (entry.getValue().isJsonPrimitive()) { // primitive type
if (entry.getValue().getAsJsonPrimitive().isString())
instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString());
else if (entry.getValue().getAsJsonPrimitive().isNumber())
instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber());
else if (entry.getValue().getAsJsonPrimitive().isBoolean())
instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean());
else
throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString()));
} else if (entry.getValue().isJsonArray()) {
instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class));
} else { // JSON object
instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class));
}
}
}
return instance;
}

}.nullSafe();
}
}

/**
* Create an instance of PetWithTypesObjectNullAndRef given an JSON string
*
* @param jsonString JSON string
* @return An instance of PetWithTypesObjectNullAndRef
* @throws IOException if the JSON string is invalid with respect to PetWithTypesObjectNullAndRef
*/
public static PetWithTypesObjectNullAndRef fromJson(String jsonString) throws IOException {
return JSON.getGson().fromJson(jsonString, PetWithTypesObjectNullAndRef.class);
}

/**
* Convert an instance of PetWithTypesObjectNullAndRef to an JSON string
*
* @return JSON string
*/
public String toJson() {
return JSON.getGson().toJson(this);
}
}

Loading
Loading