@Override
   public void visitField(QueryVisitorFieldEnvironment queryVisitorFieldEnvironment) {

      // Each new property should put as required and we should not allow additional properties.
      ArrayNode required = getRequiredArrayNode();
      required.add(queryVisitorFieldEnvironment.getFieldDefinition().getName());

      // Even if type is marked as optional in the GraphQL Schema, it must be present and
      // serialized as null into the Json response. We have to unwrap it first.
      GraphQLOutputType outputType = queryVisitorFieldEnvironment.getFieldDefinition().getType();
      Type definitionType = queryVisitorFieldEnvironment.getFieldDefinition().getDefinition().getType();
      if (TypeUtil.isNonNull(definitionType)) {
         definitionType = TypeUtil.unwrapOne(definitionType);
      }

      // Add this field to current node.
      ObjectNode fieldNode = currentNode.putObject(queryVisitorFieldEnvironment.getFieldDefinition().getName());

      TypeInfo definitionTypeInfo = TypeInfo.typeInfo(definitionType);

      // Treat most common case first: we've got a scalar property.
      if (ScalarInfo.isGraphqlSpecifiedScalar(definitionTypeInfo.getName())) {
         fieldNode.put(JSON_SCHEMA_TYPE, getJsonScalarType(definitionTypeInfo.getName()));
      } else if (outputType instanceof GraphQLObjectType) {
         // Then we deal with objects.
         fieldNode.put(JSON_SCHEMA_TYPE, JSON_SCHEMA_OBJECT_TYPE);
         ObjectNode properties = fieldNode.putObject(JSON_SCHEMA_PROPERTIES);
         parentNode.put(JSON_SCHEMA_ADDITIONAL_PROPERTIES, false);
         fieldNode.put(JSON_SCHEMA_ADDITIONAL_PROPERTIES, false);
         parentNode = fieldNode;
         currentNode = properties;
      } else if (TypeUtil.isList(definitionType)) {
         // Then we deal with lists.
         fieldNode.put(JSON_SCHEMA_TYPE, JSON_SCHEMA_ARRAY_TYPE);
         ObjectNode items = fieldNode.putObject(JSON_SCHEMA_ITEMS);

         // Depending on item type, we should initialize an object structure.
         TypeName itemTypeInfo = TypeUtil.unwrapAll(definitionType);
         if (!ScalarInfo.isGraphqlSpecifiedScalar(itemTypeInfo.getName())) {
            items.put(JSON_SCHEMA_TYPE, JSON_SCHEMA_OBJECT_TYPE);
            ObjectNode properties = items.putObject(JSON_SCHEMA_PROPERTIES);
            items.put(JSON_SCHEMA_ADDITIONAL_PROPERTIES, false);
            parentNode = items;
            currentNode = properties;
         }
      } else if (outputType instanceof GraphQLEnumType enumType) {
         // Then we deal with enumerations.
         fieldNode.put(JSON_SCHEMA_TYPE, JSON_SCHEMA_STRING_TYPE);
         ArrayNode enumNode = fieldNode.putArray(JSON_SCHEMA_ENUM);

         for (GraphQLEnumValueDefinition valDef : enumType.getValues()) {
            enumNode.add(valDef.getName());
         }
      }
   }
@Test
   public void testVisitFieldWithScalarType() {
      QueryVisitorFieldEnvironment environment = mock(QueryVisitorFieldEnvironment.class);
      GraphQLOutputType outputType = mock(GraphQLOutputType.class);
      TypeName definitionType = TypeName.newTypeName().name("String").build();

      when(environment.getFieldDefinition()).thenReturn(mock(GraphQLFieldDefinition.class));
      when(environment.getFieldDefinition().getDefinition()).thenReturn(mock(FieldDefinition.class));
      when(environment.getFieldDefinition().getType()).thenReturn(outputType);
      when(environment.getFieldDefinition().getDefinition().getType()).thenReturn(definitionType);
      when(environment.getFieldDefinition().getName()).thenReturn("scalarField");

      visitor.visitField(environment);

      JsonNode fieldNode = jsonSchemaData.get(JsonSchemaBuilderQueryVisitor.JSON_SCHEMA_PROPERTIES).get("scalarField");
      assertEquals("string", fieldNode.get(JsonSchemaBuilderQueryVisitor.JSON_SCHEMA_TYPE).asText());
   }