The samples are merged before any Java is written: every value found at the same position counts, so an array of orders gives one class typed from all of them, not from the first. A field present and non-null in every sample is a primitive, long, double or boolean; one that is null in some sample or missing from some object is boxed, as Long, Double or Boolean, because a primitive cannot hold null: Jackson 2 quietly reads null as 0, so a real 0 can no longer be told from no value, and Jackson 3 refuses it. Integers are long rather than int, as a sample says nothing about the largest ID to come, and an integer beyond long is BigInteger. Anything written with a fraction or an exponent is double, or BigDecimal if you choose it, which keeps 19.99 and even the trailing zero of 1.50 exactly; a number that a double would round, or cannot hold at all, is BigDecimal whatever you choose.
A string field is OffsetDateTime only when every sample is an ISO 8601 date-time with seconds and a Z or an offset within ±18:00, LocalDate when every sample is a date, and LocalDateTime when every sample is a date-time with no zone; anything else, including "", stays String. Jackson 2 reads these types only once the JavaTimeModule from jackson-datatype-jsr310 is registered, and even then writes an OffsetDateTime as the number 1790569800.000000000 and a LocalDate as the array [2026,9,28] until SerializationFeature.WRITE_DATES_AS_TIMESTAMPS is disabled; Jackson 3 and Spring Boot’s ObjectMapper do both already. Jackson also moves an OffsetDateTime to UTC as it reads, so +05:30 comes back as Z, the same instant, unless ADJUST_DATES_TO_CONTEXT_TIME_ZONE is disabled. Gson has no adapters for java.time, so with Gson dates stay String.
Field names are lowerCamelCase, with the key kept in the annotation: user_id, user-id, userId and USER_ID all give userId, a keyword gets an underscore (class_), and keys that give the same name are numbered. Getters follow the rule Jackson reads a name back with. A field eTag gets geteTag(), because Jackson reads getETag() as a second property, etag in Jackson 2 and ETag in Jackson 3, and writes the value twice; a boolean isActive gets getIsActive(), not the isActive() an IDE or Lombok writes, which Jackson reads as active. A key missing from some samples gets @JsonInclude(NON_NULL), so Jackson leaves it out on the way back instead of sending null; Gson leaves out every null unless serializeNulls() is set. Records have no getters, but a component may not be called hashCode or toString, so those get an underscore too. Nested objects become static nested classes of the first class, shared when identical, or separate files.