<issue_start><issue_comment>Title: Need support for Kotlin Iterables
username_0: I just implemented custom `Iterable` and `Iterator` classes which I tried passing into a (default) mapper. It serializes it as an object rather than an array. It does, however, serialize it as an array if `java.lang.Iterable` and `java.util.Iterator` are implemented.

Java and Kotlin Iterables are pretty much the same. I believe, this module should also add serializer for Kotlin iterables.
<issue_comment>username_1: PlusLT can you tell me where these classes are being used?  Are they the top level thing you are passing to mapper.writeValue() or are they contained in another object?  If top level, are you passing in a TypeRef for the generic information?  Are they also data classes or not?  Can you provide a bit more detail?
<issue_comment>username_1: Can you tell me more about your use case, because under the covers there is no difference between a Kotlin class implementing the trait Iterator and a Java one implementing java.util.Iterator.  The byte code is the same.  Even with delegation, it is the same.  Jackson cannot serialize a top-level object of unknown types as anything other than a bean unless you tell it otherwise.  Many classes implement iterator but are not intended to only be an iterator.  I tested in Java and in Kotlin with basically this code for both, and ended with exactly the same results.  Is your use case different?

```kotlin
class IteratorTests {
    class TinyPerson(val name: String, val age: Int)
    class KotlinPersonIterator(private val personList: List<TinyPerson>) : Iterator<TinyPerson> by personList.iterator() {}

    val mapper: ObjectMapper = jacksonObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, false)

    Test fun testJavaIterator() {
        val actual = """[{"name":"Fred","age":10},{"name":"Max","age":11}]"""
        val people = KotlinPersonIterator(listOf(TinyPerson("Fred", 10), TinyPerson("Max", 11)))
        val kotlinJson = mapper.writerFor<ObjectWriter>(object : TypeReference<Iterator<TinyPerson>>() {}).writeValueAsString(people)
        assertThat(actual, equalTo(kotlinJson))
    }
}
```
<issue_comment>username_1: When inside another class, same issue, needs to know how to serialize it:

```kotlin
  class Company(val name: String, [JsonSerialize(`as` = javaClass<java.util.Iterator<TinyPerson>>())] val people: KotlinPersonIterator)

    Test fun testKotlinIteratorAsField() {
        val actual = """{"name":"KidVille","people":[{"name":"Fred","age":10},{"name":"Max","age":11}]}"""
        val people = KotlinPersonIterator(listOf(TinyPerson("Fred", 10), TinyPerson("Max", 11)))
        val company = Company("KidVille", people)
        val kotlinJson = mapper.writeValueAsString(company)
        assertThat(actual, equalTo(kotlinJson))
    }
```
<issue_comment>username_1: Oh wait, the Java test does work as you describe, how odd.  Checking more...
<issue_comment>username_1: I see the problem, Kotlin auto adds fields to the class that are not present in the Java class, Jackson sees the getters/setters and says "probably a JavaBean".  So it would be hard to overcome this without doing what I do in the samples above, because there is not really a way to know if the class has real or unintended fields to switch between them.  So you have a work around above.  I'll see if the latest reflection shows these fields or not, and what they are.

if you take a java class implementing Iterator and add one method such as `public int getFake() { return 0; }` you end up with the same problem.
<issue_comment>username_1: Note the same test in Java (this is why I'm so happy in Kotlin, so verbose!):

```java

public class IteratorTestsInJava {
    class TinyPerson {
        private String name;
        private int age;

        public TinyPerson(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }
    }

    class JavaPersonIterator implements Iterator<TinyPerson> {
        private List<TinyPerson> personList;
        private Iterator<TinyPerson> personIterator;

        public JavaPersonIterator(List<TinyPerson> personList) {
            this.personList = personList;
            this.personIterator = personList.iterator();
        }

        @Override
        public boolean hasNext() {
            return personIterator.hasNext();
        }

        @Override
        public TinyPerson next() {
            return personIterator.next();
        }

        @Override
        public void remove() {
            throw new NotImplementedException();
        }
    }

    private ObjectMapper mapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, false);

    @Test
    public void testKotlinIterator() throws Exception {
        String actual = "[{\"name\":\"Fred\",\"age\":10},{\"name\":\"Max\",\"age\":11}]";
        JavaPersonIterator people1 = new JavaPersonIterator(Arrays.asList(new TinyPerson("Fred", 10), new TinyPerson("Max", 11)));
        String javaJsonNoType = mapper.writeValueAsString(people1);
        assertEquals(actual, javaJsonNoType);

        JavaPersonIterator people2 = new JavaPersonIterator(Arrays.asList(new TinyPerson("Fred", 10), new TinyPerson("Max", 11)));
        String javaJsonWithType = mapper.writerFor(new TypeReference<Iterator<TinyPerson>>() {
        }).writeValueAsString(people2);
        assertEquals(actual, javaJsonWithType);
    }

    class Company {
        private String name;
        private JavaPersonIterator people;

        public Company(String name, JavaPersonIterator people) {
            this.name = name;
            this.people = people;
        }

[Truncated]
        public JavaPersonIterator getPeople() {
            return people;
        }

        public void setPeople(JavaPersonIterator people) {
            this.people = people;
        }
    }

    @Test
    public void testJavaIteratorAsField() throws Exception {
        String actual = "{\"name\":\"KidVille\",[{\"name\":\"Fred\",\"age\":10},{\"name\":\"Max\",\"age\":11}]}";
        JavaPersonIterator people = new JavaPersonIterator(Arrays.asList(new TinyPerson("Fred", 10), new TinyPerson("Max", 11)));
        Company company = new Company("KidVille", people);
        String javaJson = mapper.writeValueAsString(company);
        assertEquals(actual, javaJson);
    }

}
```
<issue_comment>username_1: In the Kolin generated byte code is:

```
// ================com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator.class =================
// class version 50.0 (50)
// access flags 0x31
// signature Ljava/lang/Object;Ljava/util/Iterator<Lcom/fasterxml/jackson/module/kotlin/IteratorTests$TinyPerson;>;
// declaration: com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator implements java.util.Iterator<com.fasterxml.jackson.module.kotlin.IteratorTests$TinyPerson>
public final class com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator implements java/util/Iterator  {


  // access flags 0x8
  static <clinit>()V
    LDC Lcom/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator;.class
    INVOKESTATIC kotlin/jvm/internal/Reflection.createKotlinClass (Ljava/lang/Class;)Lkotlin/reflect/KClass;
    PUTSTATIC com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator.$kotlinClass : Lkotlin/reflect/KClass;
    RETURN
    MAXSTACK = 1
    MAXLOCALS = 0

  // access flags 0x1019
  public final static synthetic Lkotlin/reflect/KClass; $kotlinClass

  // access flags 0x12
  // signature Ljava/util/List<+Lcom/fasterxml/jackson/module/kotlin/IteratorTests$TinyPerson;>;
  // declaration: java.util.List<? extends com.fasterxml.jackson.module.kotlin.IteratorTests$TinyPerson>
  private final Ljava/util/List; personList

  // access flags 0x1
  // signature (Ljava/util/List<+Lcom/fasterxml/jackson/module/kotlin/IteratorTests$TinyPerson;>;)V
  // declaration: void <init>(java.util.List<? extends com.fasterxml.jackson.module.kotlin.IteratorTests$TinyPerson>)
  public <init>(Ljava/util/List;)V
    @Ljet/runtime/typeinfo/JetValueParameter;(name="personList") // parameter 0
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
   L0
   L1
    ALOAD 1
    LDC "personList"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    ALOAD 0
   L2
    LINENUMBER 16 L2
    ALOAD 1
    INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator;
    PUTFIELD com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator.$delegate_0 : Ljava/util/Iterator;
    ALOAD 0
    ALOAD 1
    PUTFIELD com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator.personList : Ljava/util/List;
    RETURN
   L3
    LOCALVARIABLE this Lcom/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator; L0 L3 0
    LOCALVARIABLE personList Ljava/util/List; L0 L3 1
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x1012
  private final synthetic Ljava/util/Iterator; $delegate_0

  // access flags 0x1
  public hasNext()Z
   L0
   L1
    ALOAD 0
    GETFIELD com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator.$delegate_0 : Ljava/util/Iterator;
    INVOKEINTERFACE java/util/Iterator.hasNext ()Z
    IRETURN
   L2
    LOCALVARIABLE this Ljava/util/Iterator; L0 L2 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public next()Lcom/fasterxml/jackson/module/kotlin/IteratorTests$TinyPerson;
  @Lorg/jetbrains/annotations/NotNull;() // invisible
   L0
   L1
    ALOAD 0
    GETFIELD com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator.$delegate_0 : Ljava/util/Iterator;
[Truncated]
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public remove()V
    NEW java/lang/UnsupportedOperationException
    DUP
    LDC "Mutating immutable collection"
    INVOKESPECIAL java/lang/UnsupportedOperationException.<init> (Ljava/lang/String;)V
    ATHROW
    MAXSTACK = 3
    MAXLOCALS = 1

  @Lkotlin/jvm/internal/KotlinClass;(abiVersion=22, kind=Lkotlin/jvm/internal/KotlinClass$Kind;.CLASS, data={"/\u0004)!2j\u001c;mS:\u0004VM]:p]&#XM]1u_JTQ\"\u0013;fe\u0006$xN\u001d+fgR\u001c(bA2p[*Ia-Y:uKJDX\u000e\u001c\u0006\u0008U\u0006\u001c7n]8o\u0015\u0019iw\u000eZ;mK*11n\u001c;mS:T\u0001\"\u0013;fe\u0006$xN\u001d\u0006\u000b)&t\u0017\u0010U3sg>t'B\u0002\u001fj]&$hH\u0003\u0006qKJ\u001cxN\u001c'jgRTA\u0001T5ti*!!.\u0019<b\u0015\u0011)H/\u001b7\u000b\u000f!\u000c7OT3yi*9!i\\8mK\u0006t'BC!o]>$\u0018\r^5p]*!a.\u001a=uA*\u0011\u0001C\u0001\u0006\u0005\u0011\u0001\u00012A\u0003\u0003\u0009\u0003A!!\u0002\u0002\u0005\u0003!\u0015QA\u0001C\u0002\u0011\r)1\u0001\u0002\u0002\u0009\u00021\u0001Qa\u0001C\u0003\u0011\u0001a\u0001!B\u0001\u0009\u0007\u0015\u0019Aq\u0001E\u0004\u0019\u0001)1\u0001\"\u0002\u0009\u00091\u0001Qa\u0001C\u0004\u0011\u0017a\u0001!B\u0001\u0009\r\u0015\u0011A1\u0002E\u0007\u000b\u0009!a\u0001c\u0003\u0006\u0007\u0011\u001d\u0001r\u0002\u0007\u0001\u0009\u0001a1!\u0007\u0004\u0006\u0003!!\u0011bA\u0005\u0003\u000b\u0005AI!L\u0008\u0005C\u0012AR!\u0009\u0004\u0006\u0003!)\u0011bA\u0005\u0003\u000b\u0005AI!V\u0002\u0005\u000b\r!Q!C\u0001\u0009\u000e5RAa\u0013\u0002\u0019\u000f\u0005\u0012Q!\u0001\u0005\u0008#\u000e\u0019A\u0001C\u0005\u0002\u0011\u000fi#\u0002B&\u00031#\u0009#!B\u0001\u0009\nE\u001b1\u0001\u0002\u0005\n\u0003!\u001dQ\u0017GC\u0018\u0009\r\u0008\u0001\u0014BO\u000b\u0009\u0001AQ!\u0004\u0004\u0006\u0003!)\u0011bA\u0005\u0003\u000b\u0005AI\u0001U\u0002\u0001C\u0009)\u0011\u0001C\u0002R\u0007\u0015!I!C\u0001\u0005\u00015\u0009\u0001R\u0002"})
  // access flags 0x19
  public final static INNERCLASS com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator com/fasterxml/jackson/module/kotlin/IteratorTests KotlinPersonIterator
  // compiled from: IteratorTests.kt
}
```
<issue_comment>username_1: So the culprit might be either: 
```
 public final static synthetic Lkotlin/reflect/KClass; $kotlinClass
```
or
```
 public final static INNERCLASS com/fasterxml/jackson/module/kotlin/IteratorTests$KotlinPersonIterator com/fasterxml/jackson/module/kotlin/IteratorTests KotlinPersonIterator
```
<issue_comment>username_1: Ah, the problem is me auto-adding JsonCreator annotations, and in BeanSerializerFactory.java (Jackson) it has:

```
if (beanDesc.hasKnownClassAnnotations()) {
                return builder.createDummy();
            }
```

which changes the behaviour... :-(
<issue_comment>username_1: @username_2 any advice on this one?  all Kotlin classes have a KotlinClass annotation with runtime-type information.  So when it is seen the BeanSerializerFactory.java calling `beanDesc.hasKnownClassAnnotations()` returns true, it doesn't care that the annotation is some random thing it does not recognize.
<issue_comment>username_1: (note the annotation inspector `_hasAnnotation` method doesn't help either because the check is if the collection of annotations size is > 0.
<issue_comment>username_1: @username_0 you have a workaround above by specifying how to serialize either the top level or a field, and I will work on resolving the issue as I can find a way to make it work more the same as java.
<issue_comment>username_2: @username_1 as far as I remember, using `@JacksonAnnotation` does not have harmful side effects so it should be ok to add. But then again it should not be necessary.

I do recall a few issues with handling of `Iterator`, and the main problem is this: given class X that implementas `Iterator`, should it be serialized as Collection? Quite often it should not, as `Iterator` is commonly used as sort of add-on to augment processing, but the type is more of a POJO.
This is why there are various heuristics to try to reason right approach.
So this is the background on why such checks are done, instead of simply just using `Iterator` for class by default.
Given the complexity it may make sense for Kotlin module to try to detect these cases when providing Serializers, in its `Serializers` implementation (if it already registers one), and not relying on core databind.

This is something that may make sense to discuss on dev list. I remember having some trouble with Guava Iterators and/or iterables.
<issue_comment>username_1: I'll look at how Guava handles it and can cover Kotlin iterators in the same way.  Subclasses of the user's, that's another story.
<issue_comment>username_2: Ok let me know, I may be able to help here. Iterators are nasty as they are essentially mix-ins, secondary interfaces, and quite often it's unclear if it's to be used as the serialization mechanism or not. Many POJOs implement it for convenience. This is the reason why it has such a low precedence if I recall correctly.<issue_closed>
<issue_comment>username_4: I am using Retrofit and Jackson converter. I cannot apply your fix there, as mapping code is incapsulated there.
When are you planning to release the correct fix?