private static <T> LogDataToJsonConverter<T> createListConverter(
      Type type, LogData.FieldGetterFactory<T> fieldGetterFactory) {
    Types.ListType list = type.asNestedType().asListType();
    Types.NestedField elementField = list.field(list.elementId());
    LogDataToJsonConverter<T> elementConverter =
        createConverter(elementField.type(), fieldGetterFactory);
    LogArrayData.ElementGetter elementGetter = LogArrayData.createElementGetter(elementField);

    return (source, context) -> {
      ArrayNode node;

      // reuse could be a NullNode if last record is null.
      if (context.node == null || context.node.isNull()) {
        node = context.mapper.createArrayNode();
      } else {
        node = (ArrayNode) context.node;
        node.removeAll();
      }
      LogArrayData array = (LogArrayData) source;
      int numElements = array.size();
      LogDataToJsonConverter.FormatConverterContext subContext =
          new LogDataToJsonConverter.FormatConverterContext(context.mapper, null);
      for (int i = 0; i < numElements; i++) {
        Object element = elementGetter.getElementOrNull(array, i);

        node.add(elementConverter.convert(element, subContext));
      }
      return node;
    };
  }
Runtime converter that converts {@link LogData} into {@link JsonNode}

@param <T> indicate an actual value wrapped within {@link LogData}
amoro-format-iceberg/src/main/java/org/apache/amoro/log/LogDataToJsonConverters.java