Full Code of square/moshi for AI

master 2d8a3cc7112f cached
183 files
1.2 MB
299.4k tokens
1070 symbols
1 requests
Download .txt
Showing preview only (1,265K chars total). Download the full file or copy to clipboard to get everything.
Repository: square/moshi
Branch: master
Commit: 2d8a3cc7112f
Files: 183
Total size: 1.2 MB

Directory structure:
gitextract_wxuqnsxb/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── renovate.json5
│   └── workflows/
│       ├── .java-version
│       ├── build.yml
│       └── release.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── build.gradle.kts
├── examples/
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── recipes/
│                               ├── ByteStrings.java
│                               ├── CardAdapter.java
│                               ├── CustomAdapterFactory.java
│                               ├── CustomAdapterWithDelegate.java
│                               ├── CustomFieldName.java
│                               ├── CustomQualifier.java
│                               ├── CustomTypeAdapter.java
│                               ├── DefaultOnDataMismatchAdapter.java
│                               ├── FallbackEnum.java
│                               ├── FromJsonWithoutStrings.java
│                               ├── IncludeNullsForAnnotatedTypes.java
│                               ├── IncludeNullsForOneType.java
│                               ├── JsonString.kt
│                               ├── MultipleFormats.java
│                               ├── ReadAndWriteRfc3339Dates.java
│                               ├── ReadJson.java
│                               ├── ReadJsonList.java
│                               ├── ReadJsonListKt.kt
│                               ├── RecoverFromTypeMismatch.java
│                               ├── Unwrap.java
│                               ├── WriteJson.java
│                               ├── models/
│                               │   ├── BlackjackHand.java
│                               │   ├── Card.java
│                               │   ├── Player.java
│                               │   ├── Suit.java
│                               │   └── Tournament.java
│                               └── package-info.java
├── gradle/
│   ├── libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── moshi/
│   ├── build.gradle.kts
│   ├── gradle.properties
│   ├── japicmp/
│   │   └── build.gradle.kts
│   ├── records-tests/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── squareup/
│   │                       └── moshi/
│   │                           └── records/
│   │                               └── RecordsTest.java
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── squareup/
│       │   │           └── moshi/
│       │   │               ├── -JsonUtf8Reader.kt
│       │   │               ├── -JsonUtf8Writer.kt
│       │   │               ├── -JsonValueReader.kt
│       │   │               ├── -JsonValueWriter.kt
│       │   │               ├── -MoshiKotlinExtensions.kt
│       │   │               ├── -MoshiKotlinTypesExtensions.kt
│       │   │               ├── FromJson.kt
│       │   │               ├── Json.kt
│       │   │               ├── JsonAdapter.kt
│       │   │               ├── JsonClass.kt
│       │   │               ├── JsonDataException.kt
│       │   │               ├── JsonEncodingException.kt
│       │   │               ├── JsonQualifier.kt
│       │   │               ├── JsonReader.kt
│       │   │               ├── JsonWriter.kt
│       │   │               ├── Moshi.kt
│       │   │               ├── ToJson.kt
│       │   │               ├── Types.kt
│       │   │               ├── internal/
│       │   │               │   ├── AdapterMethodsFactory.kt
│       │   │               │   ├── ArrayJsonAdapter.kt
│       │   │               │   ├── ClassFactory.kt
│       │   │               │   ├── ClassJsonAdapter.kt
│       │   │               │   ├── CollectionJsonAdapter.kt
│       │   │               │   ├── JsonScope.kt
│       │   │               │   ├── JsonValueSource.kt
│       │   │               │   ├── KotlinReflectTypes.kt
│       │   │               │   ├── LinkedHashTreeMap.kt
│       │   │               │   ├── MapJsonAdapter.kt
│       │   │               │   ├── NonNullJsonAdapter.kt
│       │   │               │   ├── NullSafeJsonAdapter.kt
│       │   │               │   ├── RecordJsonAdapter.kt
│       │   │               │   ├── StandardJsonAdapters.kt
│       │   │               │   └── Util.kt
│       │   │               └── package-info.java
│       │   ├── java16/
│       │   │   └── com/
│       │   │       └── squareup/
│       │   │           └── moshi/
│       │   │               └── internal/
│       │   │                   └── RecordJsonAdapter.kt
│       │   └── resources/
│       │       └── META-INF/
│       │           └── proguard/
│       │               └── moshi.pro
│       └── test/
│           └── java/
│               ├── android/
│               │   └── util/
│               │       └── Pair.java
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           ├── AdapterMethodsTest.java
│                           ├── CircularAdaptersTest.java
│                           ├── DeferredAdapterTest.java
│                           ├── FlattenTest.java
│                           ├── JsonAdapterTest.java
│                           ├── JsonCodecFactory.java
│                           ├── JsonQualifiersTest.java
│                           ├── JsonReaderPathTest.java
│                           ├── JsonReaderTest.java
│                           ├── JsonUtf8ReaderTest.java
│                           ├── JsonUtf8WriterTest.java
│                           ├── JsonValueReaderTest.java
│                           ├── JsonValueWriterTest.java
│                           ├── JsonWriterPathTest.java
│                           ├── JsonWriterTest.java
│                           ├── KotlinExtensionsTest.kt
│                           ├── MoshiTest.java
│                           ├── MoshiTesting.kt
│                           ├── ObjectAdapterTest.java
│                           ├── PromoteNameToValueTest.java
│                           ├── RecursiveTypesResolveTest.java
│                           ├── TestUtil.java
│                           ├── TypesTest.java
│                           └── internal/
│                               ├── ClassJsonAdapterTest.java
│                               ├── JsonValueSourceTest.java
│                               ├── KotlinReflectTypesTest.kt
│                               ├── LinkedHashTreeMapTest.java
│                               └── MapJsonAdapterTest.java
├── moshi-adapters/
│   ├── README.md
│   ├── build.gradle.kts
│   ├── japicmp/
│   │   └── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── squareup/
│       │               └── moshi/
│       │                   ├── Rfc3339DateJsonAdapter.kt
│       │                   └── adapters/
│       │                       ├── EnumJsonAdapter.kt
│       │                       ├── Iso8601Utils.kt
│       │                       ├── PolymorphicJsonAdapterFactory.kt
│       │                       └── Rfc3339DateJsonAdapter.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── adapters/
│                               ├── EnumJsonAdapterTest.java
│                               ├── PolymorphicJsonAdapterFactoryTest.java
│                               └── Rfc3339DateJsonAdapterTest.java
├── moshi-kotlin/
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── squareup/
│       │   │           └── moshi/
│       │   │               ├── KotlinJsonAdapterFactory.kt
│       │   │               └── kotlin/
│       │   │                   └── reflect/
│       │   │                       ├── IndexedParameterMap.kt
│       │   │                       ├── Invokable.kt
│       │   │                       ├── JvmDescriptors.kt
│       │   │                       ├── JvmSignatureSearcher.kt
│       │   │                       ├── KmExecutable.kt
│       │   │                       ├── KotlinJsonAdapterFactory.kt
│       │   │                       └── KtTypes.kt
│       │   └── resources/
│       │       └── META-INF/
│       │           └── com.android.tools/
│       │               ├── proguard/
│       │               │   └── moshi-metadata-reflect.pro
│       │               ├── r8-from-1.6.0/
│       │               │   └── moshi-metadata-reflect.pro
│       │               └── r8-upto-1.6.0/
│       │                   └── moshi-metadata-reflect.pro
│       └── test/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── kotlin/
│                               └── reflect/
│                                   └── KotlinJsonAdapterTest.kt
├── moshi-kotlin-codegen/
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── squareup/
│       │               └── moshi/
│       │                   └── kotlin/
│       │                       └── codegen/
│       │                           ├── api/
│       │                           │   ├── AdapterGenerator.kt
│       │                           │   ├── DelegateKey.kt
│       │                           │   ├── InternalMoshiCodegenApi.kt
│       │                           │   ├── Options.kt
│       │                           │   ├── ProguardRules.kt
│       │                           │   ├── PropertyGenerator.kt
│       │                           │   ├── TargetConstructor.kt
│       │                           │   ├── TargetParameter.kt
│       │                           │   ├── TargetProperty.kt
│       │                           │   ├── TargetType.kt
│       │                           │   ├── TypeRenderer.kt
│       │                           │   ├── kotlintypes.kt
│       │                           │   └── typeAliasUnwrapping.kt
│       │                           └── ksp/
│       │                               ├── AppliedType.kt
│       │                               ├── JsonClassSymbolProcessorProvider.kt
│       │                               ├── KspUtil.kt
│       │                               ├── MoshiApiUtil.kt
│       │                               ├── TargetTypes.kt
│       │                               └── shadedUtil.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── kotlin/
│                               └── codegen/
│                                   ├── JavaSuperclass.java
│                                   └── ksp/
│                                       └── JsonClassSymbolProcessorTest.kt
├── moshi-kotlin-tests/
│   ├── build.gradle.kts
│   ├── codegen-only/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── test/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── squareup/
│   │                       └── moshi/
│   │                           └── kotlin/
│   │                               └── codegen/
│   │                                   ├── CompileOnlyTests.kt
│   │                                   ├── ComplexGenericsInheritanceTest.kt
│   │                                   ├── DefaultConstructorTest.kt
│   │                                   ├── GeneratedAdaptersTest.kt
│   │                                   ├── GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter.kt
│   │                                   ├── LooksLikeAClass/
│   │                                   │   └── ClassInPackageThatLooksLikeAClass.kt
│   │                                   ├── MixingReflectAndCodeGen.kt
│   │                                   ├── MoshiKspTest.kt
│   │                                   ├── MultipleMasksTest.kt
│   │                                   └── annotation/
│   │                                       └── UppercaseInAnnotationPackage.kt
│   ├── extra-moshi-test-module/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── squareup/
│   │                       └── moshi/
│   │                           └── kotlin/
│   │                               └── codegen/
│   │                                   └── test/
│   │                                       └── extra/
│   │                                           └── AbstractClassInModuleA.kt
│   └── src/
│       └── test/
│           └── kotlin/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── kotlin/
│                               ├── DualKotlinTest.kt
│                               └── reflect/
│                                   └── KotlinJsonAdapterTest.kt
├── releasing.md
└── settings.gradle.kts

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

[*]
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length=100

[*.{kt, kts}]
kotlin_imports_layout = ascii


================================================
FILE: .gitattributes
================================================
* text=auto eol=lf

*.bat text eol=crlf
*.jar binary

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: A reproducible problem
title: ''
labels: bug
assignees: ''

---

Good bug reports include a failing test! Writing a test helps you to isolate and describe the problem, and it helps us to fix it fast. Bug reports without a failing test or reproduction steps are likely to be closed.

Here’s an example test to get you started.
https://gist.github.com/ZacSweers/0ef2c5f0e3f61f82063dd8c67d75879f

================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Question?
    url: https://stackoverflow.com/questions/tagged/moshi
    about: Please ask usage questions on Stack Overflow with the `moshi` tag.

================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea
title: ''
labels: enhancement
assignees: ''

---

Start by telling us what problem you’re trying to solve. Often a solution already exists!

Don’t send pull requests to implement new features without first getting our support. Sometimes we leave features out on purpose to keep the project small.

================================================
FILE: .github/renovate.json5
================================================
{
  $schema: 'https://docs.renovatebot.com/renovate-schema.json',
  extends: [
    'config:recommended',
  ],
  ignorePresets: [
    // Ensure we get the latest version and are not pinned to old versions.
    'workarounds:javaLTSVersions',
  ],
  customManagers: [
    // Update .java-version file with the latest JDK version.
    {
      customType: 'regex',
      fileMatch: [
        '\\.java-version$',
      ],
      matchStrings: [
        '(?<currentValue>.*)\\n',
      ],
      datasourceTemplate: 'java-version',
      depNameTemplate: 'java',
      // Only write the major version.
      extractVersionTemplate: '^(?<version>\\d+)',
    },
  ]
}


================================================
FILE: .github/workflows/.java-version
================================================
25


================================================
FILE: .github/workflows/build.yml
================================================
name: CI

on: [push, pull_request]

jobs:
  build:
    name: 'Test Mode ${{ matrix.kotlin-test-mode }}'
    runs-on: ubuntu-latest

    strategy:
      fail-fast: false
      matrix:
        kotlin-test-mode: [ 'REFLECT', 'KSP' ]

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - uses: actions/setup-java@v5
        with:
          distribution: 'zulu'
          java-version-file: .github/workflows/.java-version

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v5

      - name: Test
        run: ./gradlew build check --stacktrace -PkotlinTestMode=${{ matrix.kotlin-test-mode }}

      - name: Publish (default branch only)
        if: github.repository == 'square/moshi' && github.ref == 'refs/heads/master' && matrix.kotlin-test-mode == 'reflect'
        run: ./gradlew publish
        env:
          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }}
          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }}
          ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SECRET_KEY }}
          ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SECRET_PASSPHRASE }}


================================================
FILE: .github/workflows/release.yml
================================================
name: release

on:
  push:
    tags:
      - '**'

jobs:
  release:
    runs-on: macos-latest

    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-java@v5
        with:
          distribution: 'zulu'
          java-version-file: .github/workflows/.java-version
      - uses: gradle/actions/setup-gradle@v5
      - run: ./gradlew publish dokkaGenerate -PmavenCentralDeploymentValidation=PUBLISHED
        env:
          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }}
          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }}
          ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SECRET_KEY }}
          ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SECRET_PASSPHRASE }}

      - name: Extract release notes
        id: release_notes
        uses: ffurrer2/extract-release-notes@v3

      - name: Create release
        uses: softprops/action-gh-release@v2
        with:
          body: ${{ steps.release_notes.outputs.release_notes }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Deploy docs to website
        uses: JamesIves/github-pages-deploy-action@releases/v3
        with:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          BRANCH: site
          FOLDER: docs/2.x/
          TARGET_FOLDER: docs/2.x/
          CLEAN: true


================================================
FILE: .gitignore
================================================
.classpath
.project
.settings
eclipsebin

bin
gen
build
out
lib

target
pom.xml.*
release.properties
dependency-reduced-pom.xml

.idea
*.iml
*.ipr
*.iws
classes

obj

.DS_Store

.gradle

# Temporary until generating a docsite
docs/


================================================
FILE: CHANGELOG.md
================================================
# Change Log

## Unreleased

* None yet.


## [2.0.0-alpha.1] - 2026-01-28

* Refuse `j$.*` types from Android library desugaring as platform types.
* In-development snapshots are now published to the Central Portal Snapshots repository at https://central.sonatype.com/repository/maven-snapshots/.
* Fully supports encoding/decoding of value classes in both moshi-kotlin and code gen.
  * Note that Moshi does not propagate inlining to JSON by default. For example: `@JvmInline value class Color(val raw: Int)` is serialized to `{"raw": 12345}`.
* New `@JsonClass.inline` property to allow inlining single-property JSON classes during encoding/decoding.
  * This is particularly useful for value classes.
  * For example, a class `@JvmInline value class UserId(val id: Int)` with `inline = true` will serialize as just `123` rather than `{"id": 123}`.
* `PolymorphicJsonAdapterFactory` now invokes the fallback adapter when the label key is missing entirely from the JSON, not just when the label value is unrecognized.

### Upgrading to Moshi 2.x

In 2.x, we upgraded Moshi’s source code from .java to .kt. This update is binary-compatible with
Moshi 1.x, and so you can safely upgrade without recompiling your libraries.

The update is not source-compatible for Kotlin users.

#### JsonAdapter.Factory MutableSet

Kotlin defines both a `Set` and a `MutableSet` type, but Java has only `Set`. Implementations of
Moshi’s `JsonAdapter.Factory` interface may declare a function that accepts a `MutableSet`:

```kotlin
  override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
    ...
  }
```

Moshi 2.x requires the `annotations` argument be a `Set`:

```kotlin
  override fun create(type: Type, annotations: Set<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
    ...
  }
```

We used this shell script to migrate our code:

```shell
find . \
  -name "*.kt" \
  -exec sed -i "" 's/annotations: MutableSet<out Annotation>/annotations: Set<Annotation>/g' {} \;
```

#### Propagated Nullability in `JsonAdapter`

Previously, due to limitations of the Java type system, Moshi would always treat the type as
nullable. Kotlin's type system supports nullability natively, and Moshi now propagates nullability
information from the generic type of `JsonAdapter`.

- Calling `nullSafe()` on any `JsonAdapter` returns a `JsonAdapter<T?>` where `T` is the original type.
- Calling `nonNull()` on any `JsonAdapter` returns a `JsonAdapter<T & Any>` where `T` is the original type.
- Calling the reified `Moshi.adapter<T>()` function overloads returns a `JsonAdapter<T>` where `T` matches
 and respects the nullability of the reified type.
- Calling the `Moshi.adapter(KType)` function overloads return a `JsonAdapter` that respects the
 nullability of the `KType` but trusts that the caller specifies the correct nullability on the
 generic type argument.
- Calling any of the other `Moshi.adapter()` functions (that accept either `Type`, `Class`, or
 `KClass` types) always return nullable `JsonAdapter`s.

This is often going to be a source-breaking change for Kotlin users, but ABI-compatible. All of
Moshi's internals and code gen continue to function the same way.

#### Explicit Nullability

Moshi has functions like `JsonAdapter.fromJson(String)` that have always been _documented_ to
require non-null parameters. With Moshi 2.x that requirement is enforced by the compiler.

You may need to manually make parameters non-null (such as with `!!`) when you upgrade to Moshi 2.x.

#### Properties

We promoted `JsonWriter.setIndent()` to be a property. If you aren't already, you must use property
syntax:

```diff
  val jsonWriter = JsonWriter.of(buffer)
- jsonWriter.setIndent("  ")
+ jsonWriter.indent = "  "
```

#### moshi-kotlin-codegen

The KSP code generator now supports (and requires) KSP2.

#### moshi-kotlin

This release switches `KotlinJsonAdapterFactory` to use `kotlin-metadata` instead of `kotlin-reflect`. This is a lightweight alternative to kotlin-reflect and satisfies moshi-kotlin's requirements. It is also ~20% more performant at runtime.

* This is not a source or ABI breaking change but if you were relying on the transitive `kotlin-reflect` dependency you will need to add it explicitly.
* No longer encodes properties/fields from supertypes that are platform types.

## [1.15.2] - 2024-12-05

 * Do not generate conditional shrinker rules (i.e., `-if`) when the rule is already predicated on the presence of the target type (as `-keepnames` and `-keepclassmembers` are).
   This will improve shrinker performance for projects with hundreds of model types, as conditional rules are more expensive to evaluate.


## [1.15.1] - 2024-01-30

 * Upgrade to Okio `3.7.0`


## [1.15.0] - 2023-05-12

 * Upgrade to Kotlin `1.8.21`.
 * Upgrade to KSP `1.8.21-1.0.11`.
 * Upgrade to kotlinx-metadata `0.6.0`.
 * Upgrade to KotlinPoet `1.13.2`.
 * Support Kotlin language version `1.9.0` in KAPT.
 * Include name of the type being processed when creating the adapterGenerator fails in KSP.
 * Suppress `UNUSED_PARAMETER` in generated code.
 * Deprecate KAPT code gen. Please migrate to KSP, we will remove KAPT support in a future release. This release will also print an annoying noisy warning in KAPT processing if you use it.

## [1.14.0] - 2022-09-06

 * Upgrade: [Kotlin 1.7.0][kotlin_1_7_0].
 * Upgrade [KotlinPoet 1.12.0][kotlinpoet_1_12_0].
   * Moshi no longer shades kotlinpoet-ksp APIs, meaning they can be updated independently of Moshi updates.
 * Upgrade: [KSP 1.7.0-1.0.6][ksp_1_7_0_1_0_6].
 * Upgrade: [kotlinx-metadata 0.5.0][kotlinx_metadata_0_5_0], allowing reading of kotlin 1.8 APIs too.


## [1.13.0] - 2021-12-08

 * New: Support for [Kotlin Symbol Processing (KSP)][ksp]. KSP is an alternative to annotation
   processing code gen. It's builds faster and better supports Kotlin language features.

   To use KSP in your application you must enable the KSP Gradle plugin and add a KSP dependency
   on Moshi codegen.

    ```
    plugins {
      id("com.google.devtools.ksp").version("1.6.0-1.0.1")
    }

    dependencies {
      ksp("com.squareup.moshi:moshi-kotlin-codegen:1.13.0")
    }
    ```

   If you're switching from annotation processing (kapt) to KSP, you should remove the kapt plugin
   and the kapt Moshi dependency.

 * New: `@Json(ignore = true)` is a Moshi-specific way to exclude properties from JSON encoding
   and decoding.
 * New: Support Java 16 records. (Moshi still requires Java 8 only; we're shipping a [multi-release
   jar][mrjar] to better support modern JVMs.)
 * New: Option to disable generating R8/ProGuard files. These files prevent code shrinkers from
   removing files that support JSON processing. If you're not using ProGuard or R8, you can skip
   this step.

    ```
    ksp {
      arg("moshi.generateProguardRules", "false")
    }
    ```

 * Upgrade: [Kotlin 1.6.0][kotlin_1_6_0].

## [1.12.0] - 2021-04-01

 * New: Improve generated code performance when all properties are set.
 * Fix: Don't crash on a missing type element like `@SuppressLint`.
 * Fix: Update the JVM metadata library to avoid problems on Kotlin 1.5.0-M2.
 * Fix: Support generic arrays with defaults in generated adapters.
 * Fix: Don't generate code with simple name collisions.
 * Upgrade: [Okio 2.10.0][okio_2_10_0].
 * Upgrade: [Kotlin 1.4.31][kotlin_1_4_31].

## [1.11.0] - 2020-10-04

 * New: Kotlin extension functions and properties. Use of these extensions is only possible from
   Kotlin, and requires the Kotlin stdlib dependency. This release does not have any Kotlin
   requirement and can be used Kotlin-free from Java.

    ```kotlin
    /** Extension alternative to [Types.nextAnnotations()]. */
    fun <reified T : Annotation> Set<Annotation>.nextAnnotations(): Set<Annotation>?

    /** Extension alternative to [Types.getRawType()]. */
    val Type.rawType: Class<*>

    /** Extension alternative to [Types.arrayOf()]. */
    fun KClass<*>.asArrayType(): GenericArrayType

    /** Extension alternative to [Types.arrayOf()]. */
    fun Type.asArrayType(): GenericArrayType
    ```

 * New: Experimental Kotlin extensions. These depend on unreleased APIs and may break in a future
   release of Kotlin. If you are comfortable with this, add `@ExperimentalStdlibApi` at the callsite
   or add this argument to your Kotlin compiler: `"-Xopt-in=kotlin.ExperimentalStdlibApi"`.

    ```kotlin
    /** Returns the adapter for [T]. */
    inline fun <reified T> Moshi.adapter(): JsonAdapter<T>

    /** Returns the adapter for [ktype]. */
    fun <T> Moshi.adapter(ktype: KType): JsonAdapter<T>

    /** Adds an adapter for [T]. */
    inline fun <reified T> Moshi.Builder.addAdapter(adapter: JsonAdapter<T>): Moshi.Builder

    /** Extension alternative to [Types.arrayOf()]. */
    fun KType.asArrayType(): GenericArrayType

    /** Extension alternative to [Types.subtypeOf()]. */
    inline fun <reified T> subtypeOf(): WildcardType

    /** Extension alternative to [Types.supertypeOf()]. */
    inline fun <reified T> supertypeOf(): WildcardType
    ```

 * New: `JsonReader.nextSource()`. This returns an Okio `BufferedSource` that streams the UTF-8
   bytes of a JSON value. Use this to accept JSON values without decoding them, to delegate to
   another JSON processor, or for streaming access to very large embedded values.
 * New: `Moshi.Builder.addLast()`. Use this when installing widely-applicable adapter factories like
   `KotlinJsonAdapterFactory`. Adapters registered with `add()` are preferred (in the order they
   were added), followed by all adapters registered with `addLast()` (also in the order they were
   added). This precedence is retained when `Moshi.newBuilder()` is used.
 * New: `setTag()`, `tag()` methods on `JsonReader` and `JsonWriter`. Use these as a side-channel
   between adapters and their uses. For example, a tag may be used to track use of unexpected
   data in a custom adapter.
 * Fix: Don't crash with a `StackOverflowError` decoding backward-referencing type variables in
   Kotlin. This caused problems for parameterized types like `MyInterface<E : Enum<E>>`.
 * Upgrade: [Okio 1.17.5][okio_1_7_5].
 * Upgrade: [Kotlin 1.4.10][kotlin_1_4_10].

## [1.10.0] - 2020-08-26

 * New: Upgrade to Kotlin 1.4.0.
 * New: `JsonReader.promoteNameToValue()` makes it easier to build custom `Map` adapters.
 * New: `Options.strings()`.
 * New: `PolymorphicJsonAdapterFactory.withFallbackJsonAdapter()` makes it possible to handle
   unrecognized types when encoding and decoding.
 * New: Add `JsonWriter.jsonValue` API
 * New: Code gen now generates precise proguard rules on-the-fly.
 * New: Improve error when incorrectly trying to use a collection class like `ArrayList` instead of `List`
 * Fix: Prevent R8 from keeping all `@Metadata` annotations
 * Fix: Avoid VerifyErrors on Android 4.4 devices when using R8
 * Fix: Fix resolution of types in superclass settable properties

## Version 1.9.3

_2020-06-11_

 * Fix: Tweak a shrinker rule to mitigate an R8 bug which was causing classes unrelated to the Kotlin adpater code generation to be retained.
 * Fix: Ensure that the Kotlin adapter code generation does not line wrap in the middle of a string if your JSON keys contain spaces.
 * Fix: Strip type annotations before emitting type references like `Foo::class` in the Kotlin adapter code generation.
 * Fix: Separate the runtime check for Kotlin's `DefaultConstructorMarker` from the check for `Metadata`. A shrinker may have removed `Metadata` and we should still check for `DefaultConstructorMarker`.


## Version 1.9.2

_2019-11-17_

 * Fix: Generate correct adapters for several special cases including reified inline types, public
   classes enclosed in internal classes, deprecated types with `-Werror`, primitives in type
   parameters, nullables in type parameters, and type aliases in type parameters.


## Version 1.9.1

_2019-10-30_

 * Fix: "abstract function ... cannot have code" code gen crash when parsing Kotlin metadata.
 * Fix: Generate code to support constructors with more than 32 parameters. The 1.9.0 release had
   a regression where classes with 33+ parameters would crash upon decoding.
 * Fix: Generate code to support more constructor cases, such as classes with non-property
   parameters and classes with multiple constructors.
 * Fix: Generate code to handle type aliases in type parameters.


## Version 1.9.0

_2019-10-29_

 * **This release requires kotlin-reflect or moshi-kotlin-codegen for all Kotlin classes.**

   Previously Moshi wouldn't differentiate between Kotlin classes and Java classes if Kotlin was
   not configured. This caused bad runtime behavior such as putting null into non-nullable fields!
   If you attempt to create an adapter for a Kotlin type, Moshi will throw an
   `IllegalArgumentException`.

   Fix this with either the reflection adapter:

   ```kotlin
   val moshi = Moshi.Builder()
       // ... add your own JsonAdapters and factories ...
       .add(KotlinJsonAdapterFactory())
       .build()
   ```

   Or the codegen annotation processor:

   ```kotlin
   @JsonClass(generateAdapter = true)
   data class BlackjackHand(
           val hidden_card: Card,
           val visible_cards: List<Card>
   )
   ```

   The [Kotlin documentation][moshi_kotlin_docs] explains the required build configuration changes.

 * New: Change how Moshi's generated adapters call constructors. Previous generated code used a
   combination of the constructor and `copy()` method to set properties that have default values.
   With this update we call the same synthetic constructor that Kotlin uses. This is less surprising
   though it requires us to generate some tricky code.
 * New: Make `Rfc3339DateJsonAdapter` null-safe. Previously Moshi would refuse to decode null dates.
   Restore that behavior by explicitly forbidding nulls with `Rfc3339DateJsonAdapter().nonNull()`.
 * New: Require Kotlin 1.3.50 or newer.
 * New: `JsonWriter.valueSink()` streams JSON-formatted data inline. Use this to do basic includes
   of raw JSON within a streamed document.
 * New: Support Gradle incremental processing in code gen.
 * New: Improve error messages. This includes better errors when field names and JSON names
   disagree, and when failing on an unknown field.
 * New: Support default values in `PolymorphicJsonAdapterFactory`.
 * New: Permit multiple labels for each subtype in `PolymorphicJsonAdapterFactory`. The first label
   is used when writing an object to JSON.
 * New: Forbid automatic encoding of platform classes in `kotlinx`. As with `java.*`, `android.*`,
   and `kotlin.*` Moshi wants you to specify how to encode platform types.
 * New: `@JsonClass(generator=...)` makes it possible for third-party libraries to provide generated
   adapters when Moshi's default adapters are insufficient.
 * Fix: Simplify wildcard types like `List<? extends Number>` to their base types `List<Number>`
   when finding type adapters. This is especially useful with Kotlin where wildcards may be added
   automatically.
 * Fix: Use the correct name when the `@Json` annotation uses field targeting like `@field:Json`.
 * Fix: Support multiple transient properties in `KotlinJsonAdapter`.
 * Fix: Don't explode attempting to resolve self-referential type variables like in
   `Comparable<T extends Comparable<T>>`.
 * Fix: Don't infinite loop on `skipValue()` at the end an object or array. Also disallow calling
   `skipValue()` at the end of a document.


## Version 1.8.0

_2018-11-09_

 * New: Support JSON objects that include type information in the JSON. The new
   `PolymorphicJsonAdapterFactory` writes a type field when encoding, and reads it when decoding.
 * New: Fall back to the reflection-based `KotlinJsonAdapterFactory` if it is enabled and a
   generated adapter is not found. This makes it possible to use reflection-based JSON adapters in
   development (so you don't have to wait for code to be regenerated on every build) and generated
   JSON adapters in production (so you don't need the kotlin-reflect library).
 * New: The `peekJson()` method on `JsonReader` let you read ahead on a JSON stream without
   consuming it. This builds on Okio's new `Buffer.peek()` API.
 * New: The `beginFlatten()` and `endFlatten()` methods on `JsonWriter` suppress unwanted nesting
   when composing adapters. Previously it was necessary to flatten objects in memory before writing.
 * New: Upgrade to Okio 1.16.0. We don't yet require Kotlin-friendly Okio 2.1 but Moshi works fine
   with that release.

   ```kotlin
   implementation("com.squareup.okio:okio:1.16.0")
   ```

 * Fix: Don't return partially-constructed adapters when using a Moshi instance concurrently.
 * Fix: Eliminate warnings and errors in generated `.kt` triggered by type variance, primitive
   types, and required values.
 * Fix: Improve the supplied rules (`moshi.pro`) to better retain symbols used by Moshi. We
   recommend R8 when shrinking code.
 * Fix: Remove code generation companion objects. This API was neither complete nor necessary.


## Version 1.7.0

_2018-09-24_

 * New: `EnumJsonAdapter` makes it easy to specify a fallback value for unknown enum constants.
   By default Moshi throws an `JsonDataException` if it reads an unknown enum constant. With this
   you can specify a fallback value or null.

   ```java
   new Moshi.Builder()
       .add(EnumJsonAdapter.create(IsoCurrency.class)
           .withUnknownFallback(IsoCurrency.USD))
       .build();
   ```

   Note that this adapter is in the optional `moshi-adapters` module.

   ```groovy
   implementation 'com.squareup.moshi:moshi-adapters:1.7.0'
   ```

 * New: Embed R8/ProGuard rules in the `.jar` file.
 * New: Use `@CheckReturnValue` in more places. We hope this will encourage you to use `skipName()`
   instead of `nextName()` for better performance!
 * New: Forbid automatic encoding of platform classes in `androidx`. As with `java.*`, `android.*`,
   and `kotlin.*` Moshi wants you to specify how to encode platform types.
 * New: Improve error reporting when creating an adapter fails.
 * New: Upgrade to Okio 1.15.0. We don't yet require Kotlin-friendly Okio 2.x but Moshi works fine
   with that release.

   ```groovy
   implementation 'com.squareup.okio:okio:1.15.0'
   ```

 * Fix: Return false from `JsonReader.hasNext()` at document's end.
 * Fix: Improve code gen to handle several broken cases. Our generated adapters had problems with
   nulls, nested parameterized types, private transient properties, generic type aliases, fields
   with dollar signs in their names, and named companion objects.


## Version 1.6.0

_2018-05-14_

 * **Moshi now supports codegen for Kotlin.** We've added a new annotation processor that generates
   a small and fast JSON adapter for your Kotlin types. It can be used on its own or with the
   existing `KotlinJsonAdapterFactory` adapter.

 * **Moshi now resolves all type parameters.** Previously Moshi wouldn't resolve type parameters on
   top-level classes.

 * New: Support up to 255 levels of nesting when reading and writing JSON. Previously Moshi would
   reject JSON input that contained more than 32 levels of nesting.
 * New: Write encoded JSON to a stream with `JsonWriter.value(BufferedSource)`. Use this to emit a
   JSON value without decoding it first.
 * New: `JsonAdapter.nonNull()` returns a new JSON adapter that forbids explicit nulls in the JSON
   body. Use this to detect and fail eagerly on unwanted nulls.
 * New: `JsonReader.skipName()` is like `nextName()` but it avoids allocating when a name is
   unknown. Use this when `JsonReader.selectName()` returns -1.
 * New: Automatic module name of `com.squareup.moshi` for use with the Java Platform Module System.
   This moves moshi-adapters into its own `.adapters` package and forwards the existing adapter. It
   moves the moshi-kotlin into its own `.kotlin.reflect` package and forwards the existing adapter.
 * New: Upgrade to Okio 1.14.0.

    ```xml
     <dependency>
       <groupId>com.squareup.okio</groupId>
       <artifactId>okio</artifactId>
       <version>1.14.0</version>
     </dependency>

     com.squareup.okio:okio:1.14.0
    ```

 * Fix: Fail fast if there are trailing non-whitespace characters in the JSON passed to
   `JsonAdapter.fromJson(String)`. Previously such data was ignored!
 * Fix: Fail fast when Kotlin types are abstract, inner, or object instances.
 * Fix: Fail fast if `name()` is called out of sequence.
 * Fix: Handle asymmetric `Type.equals()` methods when doing type comparisons. Previously it was
   possible that a registered type adapter would not be used because its `Type.equals()` method was
   not consistent with a user-provided type.
 * Fix: `JsonValueReader.selectString()` now returns -1 for non-strings instead of throwing.
 * Fix: Permit reading numbers as strings when the `JsonReader` was created from a JSON value. This
   was always supported when reading from a stream but broken when reading from a decoded value.
 * Fix: Delegate to user-adapters in the adapter for Object.class. Previously when Moshi encountered
   an opaque Object it would only use the built-in adapters. With this change user-installed
   adapters for types like `String` will always be honored.

## Version 1.5.0

_2017-05-14_

 *  **Moshi now uses `@Nullable` to annotate all possibly-null values.** We've added a compile-time
    dependency on the JSR 305 annotations. This is a [provided][maven_provided] dependency and does
    not need to be included in your build configuration, `.jar` file, or `.apk`. We use
    `@ParametersAreNonnullByDefault` and all parameters and return types are never null unless
    explicitly annotated `@Nullable`.

 *  **Warning: Moshi APIs in this update are source-incompatible for Kotlin callers.** Nullability
    was previously ambiguous and lenient but now the compiler will enforce strict null checks.

 *  **Kotlin models are now supported via the `moshi-kotlin` extension.** `KotlinJsonAdapterFactory`
    is the best way to use Kotlin with Moshi. It honors default values and is null-safe. Kotlin
    users that don't use this factory should write custom adapters for their JSON types. Otherwise
    Moshi cannot properly initialize delegated properties of the objects it decodes.

 *  New: Upgrade to Okio 1.13.0.

    ```xml
     <dependency>
       <groupId>com.squareup.okio</groupId>
       <artifactId>okio</artifactId>
       <version>1.13.0</version>
     </dependency>

     com.squareup.okio:okio:1.13.0
    ```

 *  New: You may now declare delegates in `@ToJson` and `@FromJson` methods. If one of the arguments
    to the method is a `JsonAdapter` of the same type, that will be the next eligible adapter for
    that type. This may be useful for composing adapters.
 *  New: `Types.equals(Type, Type)` makes it easier to compare types in `JsonAdapter.Factory`.
 *  Fix: Retain the sign on negative zero.


## Version 1.4.0

_2017-02-04_

Moshi 1.4 is a major release that adds _JSON values_ as a core part of the library. We consider any
Java object comprised of maps, lists, strings, numbers, booleans and nulls to be a JSON value. These
are equivalent to parsed JSON objects in JavaScript, [Gson][gson]’s `JsonElement`, and
[Jackson][jackson]’s `JsonNode`. Unlike Jackson and Gson, Moshi just uses Java’s built-in types for
its values:

<table>
<tr><th></th><th>JSON type</th><th>Java type</th></tr>
<tr><td>{...}</td><td>Object</td><td>Map&lt;String, Object&gt;</th></tr>
<tr><td>[...]</td><td>Array</td><td>List&lt;Object&gt;</th></tr>
<tr><td>"abc"</td><td>String</td><td>String</th></tr>
<tr><td>123</td><td>Number</td><td>Double, Long, or BigDecimal</th></tr>
<tr><td>true</td><td>Boolean</td><td>Boolean</th></tr>
<tr><td>null</td><td>null</td><td>null</th></tr>
</table>

Moshi's new API `JsonAdapter.toJsonValue()` converts your application classes to JSON values
comprised of the above types. Symmetrically, `JsonAdapter.fromJsonValue()` converts JSON values to
your application classes.

 *  New: `JsonAdapter.toJsonValue()` and `fromJsonValue()`.
 *  New: `JsonReader.readJsonValue()` reads a JSON value from a stream.
 *  New: `Moshi.adapter(Type, Class<? extends Annotation>)` lets you look up the adapter for a
    qualified type.
 *  New: `JsonAdapter.serializeNulls()` and `indent()` return JSON adapters that customize the
    format of the encoded JSON.
 *  New: `JsonReader.selectName()` and `selectString()` optimize decoding JSON with known names and
    values.
 *  New: `Types.nextAnnotations()` reduces the amount of code required to implement a custom
    `JsonAdapter.Factory`.
 *  Fix: Don't fail on large longs that have a fractional component like `9223372036854775806.0`.

## Version 1.3.1

_2016-10-21_

 *  Fix: Don't incorrectly report invalid input when a slash character is escaped. When we tightened
    our invalid escape handling we missed the one character that is valid both escaped `\/` and
    unescaped `/`.

## Version 1.3.0

_2016-10-15_

 *  New: Permit `@ToJson` and `@FromJson` methods to take any number of `JsonAdapter` parameters to
    delegate to. This is supported for `@ToJson` methods that take a `JsonWriter` and `@FromJson`
    methods that take a `JsonReader`.
 *  New: Throw `JsonEncodingException` when the incoming data is not valid JSON. Use this to
    differentiate data format problems from connectivity problems.
 *  New: Upgrade to Okio 1.11.0.

    ```xml
    <dependency>
      <groupId>com.squareup.okio</groupId>
      <artifactId>okio</artifactId>
      <version>1.11.0</version>
    </dependency>
    ```

 *  New: Omit Kotlin (`kotlin.*`) and Scala (`scala.*`) platform types when encoding objects using
    their fields. This should make it easier to avoid unexpected dependencies on platform versions.
 *  Fix: Explicitly limit reading and writing to 31 levels of nested structure. Previously no
    specific limit was enforced, but deeply nested documents would fail with either an
    `ArrayIndexOutOfBoundsException` due to a bug in `JsonWriter`'s path management, or a
    `StackOverflowError` due to excessive recursion.
 *  Fix: Require enclosed types to specify their enclosing type with
    `Types.newParameterizedTypeWithOwner()`. Previously this API did not exist and looking up
    adapters for enclosed parameterized types was not possible.
 *  Fix: Fail on invalid escapes. Previously any character could be escaped. With this fix only
    characters permitted to be escaped may be escaped. Use `JsonReader.setLenient(true)` to read
    JSON documents that escape characters that should not be escaped.

## Version 1.2.0

_2016-05-28_

 *  New: Take advantage of Okio's new `Options` feature when reading field names and enum values.
    This has a significant impact on performance. We measured parsing performance improve from 89k
    ops/sec to 140k ops/sec on one benchmark on one machine.
 *  New: Upgrade to Okio 1.8.0.

    ```xml
    <dependency>
      <groupId>com.squareup.okio</groupId>
      <artifactId>okio</artifactId>
      <version>1.8.0</version>
    </dependency>
    ```

 *  New: Support types that lack no-argument constructors objects on Android releases prior to
    Gingerbread.
 *  Fix: Add writer value overload for boxed booleans. Autoboxing resolves boxed longs and doubles
    to `value(Number)`, but a boxed boolean would otherwise resolve to value(boolean) with an
    implicit call to booleanValue() which has the potential to throw NPEs.
 *  Fix: Be more aggressive about canonicalizing types.

## Version 1.1.0

_2016-01-19_

 *  New: Support [RFC 7159][rfc_7159], the latest JSON specification. This removes the constraint
    that the root value must be an array or an object. It may now take any value: array, object,
    string, number, boolean, or null. Previously this was only permitted if the adapter was
    configured to be lenient.
 *  New: Enum constants may be annotated with `@Json` to customize their encoded value.
 *  New: Create new builder from Moshi instance with `Moshi.newBuilder()`.
 *  New: `Types.getRawType()` and `Types.collectionElementType()` APIs to assist in defining generic
    type adapter factories.

## Version 1.0.0

_2015-09-27_

 *  **API Change**: Replaced `new JsonReader()` with `JsonReader.of()` and `new JsonWriter()` with
    `JsonWriter.of()`. If your code calls either of these constructors it will need to be updated to
    call the static factory method instead.
 *  **API Change**: Don’t throw `IOException` on `JsonAdapter.toJson(T)`. Code that calls this
    method may need to be fixed to no longer catch an impossible `IOException`.
 *  Fix: the JSON adapter for `Object` no longer fails when encountering `null` in the stream.
 *  New: `@Json` annotation can customize a field's name. This is particularly handy for fields
    whose names are Java keywords, like `default` or `public`.
 *  New: `Rfc3339DateJsonAdapter` converts between a `java.util.Date` and a string formatted with
    RFC 3339 (like `2015-09-26T18:23:50.250Z`). This class is in the new `moshi-adapters`
    subproject. You will need to register this adapter if you want this date formatting behavior.
    See it in action in the [dates example][dates_example].
 *  New: `Moshi.adapter()` keeps a cache of all created adapters. For best efficiency, application
    code should keep a reference to required adapters in a field.
 *  New: The `Types` factory class makes it possible to compose types like `List<Card>` or
    `Map<String, Integer>`. This is useful to look up JSON adapters for parameterized types.
 *  New: `JsonAdapter.failOnUnknown()` returns a new JSON adapter that throws if an unknown value is
    encountered on the stream. Use this in development and debug builds to detect typos in field
    names. This feature shouldn’t be used in production because it makes migrations very difficult.

## Version 0.9.0

_2015-06-16_

 *  Databinding for primitive types, strings, enums, arrays, collections, and maps.
 *  Databinding for plain old Java objects.
 *  [JSONPath](http://goessner.net/articles/JsonPath/) support for both `JsonReader` and
    `JsonWriter`.
 *  Throw `JsonDataException` when there’s a data binding problem.
 *  Adapter methods: `@ToJson` and `@FromJson`.
 *  Qualifier annotations: `@JsonQualifier` to permit different type adapters for the same Java
    type.
 *  Imported code from Gson: `JsonReader`, `JsonWriter`. Also some internal classes:
    `LinkedHashTreeMap` for hash-collision avoidance and `Types` for typesafe databinding.


 [dates_example]: https://github.com/square/moshi/blob/master/examples/src/main/java/com/squareup/moshi/recipes/ReadAndWriteRfc3339Dates.java
 [gson]: https://github.com/google/gson
 [jackson]: http://wiki.fasterxml.com/JacksonHome
 [kotlin_1_4_10]: https://github.com/JetBrains/kotlin/releases/tag/v1.4.10
 [kotlin_1_4_31]: https://github.com/JetBrains/kotlin/releases/tag/v1.4.31
 [kotlin_1_6_0]: https://github.com/JetBrains/kotlin/releases/tag/v1.6.0
 [kotlin_1_7_0]: https://github.com/JetBrains/kotlin/releases/tag/v1.7.0
 [kotlinpoet_1_12_0]: https://github.com/square/kotlinpoet/releases/tag/1.12.0
 [kotlinx_metadata_0_5_0]: https://github.com/JetBrains/kotlin/blob/master/libraries/kotlinx-metadata/jvm/ChangeLog.md#050
 [ksp]: https://github.com/google/ksp
 [ksp_1_7_0_1_0_6]: https://github.com/google/ksp/releases/tag/1.7.10-1.0.6
 [maven_provided]: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
 [moshi_kotlin_docs]: https://github.com/square/moshi/blob/master/README.md#kotlin
 [mrjar]: https://openjdk.java.net/jeps/238
 [okio_1_7_5]: https://square.github.io/okio/changelog/#version-1175
 [okio_2_10_0]: https://square.github.io/okio/changelog/#version-2100
 [rfc_7159]: https://tools.ietf.org/html/rfc7159


================================================
FILE: CONTRIBUTING.md
================================================
Contributing
============

If you would like to contribute code to Moshi you can do so through GitHub by
forking the repository and sending a pull request.

When submitting code, please make every effort to follow existing conventions
and style in order to keep the code as readable as possible. Please also make
sure your code compiles by running `./gradlew build`. For any formatting errors,
run `./gradlew spotlessApply` to fix them.

Before your code can be accepted into the project you must also sign the
[Individual Contributor License Agreement (CLA)][1].


 [1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1


================================================
FILE: LICENSE.txt
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
Moshi
=====

Moshi is a modern JSON library for Android, Java and Kotlin. It makes it easy to parse JSON into Java and Kotlin
classes:

_Note: The Kotlin examples of this README assume use of either Kotlin code gen or `KotlinJsonAdapterFactory` for reflection. Plain Java-based reflection is unsupported on Kotlin classes._

<details>
  <summary>Java</summary>

```java
String json = ...;

Moshi moshi = new Moshi.Builder().build();
JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);

BlackjackHand blackjackHand = jsonAdapter.fromJson(json);
System.out.println(blackjackHand);
```
</details>

<details open>
  <summary>Kotlin</summary>

```kotlin
val json: String = ...

val moshi: Moshi = Moshi.Builder().build()
val jsonAdapter: JsonAdapter<BlackjackHand> = moshi.adapter<BlackjackHand>()

val blackjackHand = jsonAdapter.fromJson(json)
println(blackjackHand)
```
</details>

And it can just as easily serialize Java or Kotlin objects as JSON:

<details>
    <summary>Java</summary>

```java
BlackjackHand blackjackHand = new BlackjackHand(
    new Card('6', SPADES),
    Arrays.asList(new Card('4', CLUBS), new Card('A', HEARTS)));

Moshi moshi = new Moshi.Builder().build();
JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);

String json = jsonAdapter.toJson(blackjackHand);
System.out.println(json);
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
val blackjackHand = BlackjackHand(
    Card('6', SPADES),
    listOf(Card('4', CLUBS), Card('A', HEARTS))
  )

val moshi: Moshi = Moshi.Builder().build()
val jsonAdapter: JsonAdapter<BlackjackHand> = moshi.adapter<BlackjackHand>()

val json: String = jsonAdapter.toJson(blackjackHand)
println(json)
```
</details>

### Built-in Type Adapters

Moshi has built-in support for reading and writing Java’s core data types:

 * Primitives (int, float, char...) and their boxed counterparts (Integer, Float, Character...).
 * Arrays, Collections, Lists, Sets, and Maps
 * Strings
 * Enums

It supports your model classes by writing them out field-by-field. In the example above Moshi uses
these classes:

<details>
    <summary>Java</summary>

```java
class BlackjackHand {
  public final Card hidden_card;
  public final List<Card> visible_cards;
  ...
}

class Card {
  public final char rank;
  public final Suit suit;
  ...
}

enum Suit {
  CLUBS, DIAMONDS, HEARTS, SPADES;
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class BlackjackHand(
  val hidden_card: Card,
  val visible_cards: List<Card>,
  ...
)

class Card(
  val rank: Char,
  val suit: Suit
  ...
)

enum class Suit {
  CLUBS, DIAMONDS, HEARTS, SPADES;
}
```
</details>


to read and write this JSON:

```json
{
  "hidden_card": {
    "rank": "6",
    "suit": "SPADES"
  },
  "visible_cards": [
    {
      "rank": "4",
      "suit": "CLUBS"
    },
    {
      "rank": "A",
      "suit": "HEARTS"
    }
  ]
}
```

The [Javadoc][javadoc] catalogs the complete Moshi API, which we explore below.

### Custom Type Adapters

With Moshi, it’s particularly easy to customize how values are converted to and from JSON. A type
adapter is any class that has methods annotated `@ToJson` and `@FromJson`.

For example, Moshi’s default encoding of a playing card is verbose: the JSON defines the rank and
suit in separate fields: `{"rank":"A","suit":"HEARTS"}`. With a type adapter, we can change the
encoding to something more compact: `"4H"` for the four of hearts or `"JD"` for the jack of
diamonds:

<details>
    <summary>Java</summary>

```java
class CardAdapter {
  @ToJson String toJson(Card card) {
    return card.rank + card.suit.name().substring(0, 1);
  }

  @FromJson Card fromJson(String card) {
    if (card.length() != 2) throw new JsonDataException("Unknown card: " + card);

    char rank = card.charAt(0);
    switch (card.charAt(1)) {
      case 'C': return new Card(rank, Suit.CLUBS);
      case 'D': return new Card(rank, Suit.DIAMONDS);
      case 'H': return new Card(rank, Suit.HEARTS);
      case 'S': return new Card(rank, Suit.SPADES);
      default: throw new JsonDataException("unknown suit: " + card);
    }
  }
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class CardAdapter {
  @ToJson fun toJson(card: Card): String {
    return card.rank + card.suit.name.substring(0, 1)
  }

  @FromJson fun fromJson(card: String): Card {
    if (card.length != 2) throw JsonDataException("Unknown card: $card")

    val rank = card[0]
    return when (card[1]) {
      'C' -> Card(rank, Suit.CLUBS)
      'D' -> Card(rank, Suit.DIAMONDS)
      'H' -> Card(rank, Suit.HEARTS)
      'S' -> Card(rank, Suit.SPADES)
      else -> throw JsonDataException("unknown suit: $card")
    }
  }
}
```
</details>

Register the type adapter with the `Moshi.Builder` and we’re good to go.

<details>
    <summary>Java</summary>

```java
Moshi moshi = new Moshi.Builder()
    .add(new CardAdapter())
    .build();
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
val moshi = Moshi.Builder()
    .add(CardAdapter())
    .build()
```
</details>

Voilà:

```json
{
  "hidden_card": "6S",
  "visible_cards": [
    "4C",
    "AH"
  ]
}
```

#### Another example

Note that the method annotated with `@FromJson` does not need to take a String as an argument.
Rather it can take input of any type and Moshi will first parse the JSON to an object of that type
and then use the `@FromJson` method to produce the desired final value. Conversely, the method
annotated with `@ToJson` does not have to produce a String.

Assume, for example, that we have to parse a JSON in which the date and time of an event are
represented as two separate strings.

```json
{
  "title": "Blackjack tournament",
  "begin_date": "20151010",
  "begin_time": "17:04"
}
```

We would like to combine these two fields into one string to facilitate the date parsing at a
later point. Also, we would like to have all variable names in CamelCase. Therefore, the `Event`
class we want Moshi to produce like this:

<details>
    <summary>Java</summary>

```java
class Event {
  String title;
  String beginDateAndTime;
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class Event(
  val title: String,
  val beginDateAndTime: String
)
```
</details>

Instead of manually parsing the JSON line per line (which we could also do) we can have Moshi do the
transformation automatically. We simply define another class `EventJson` that directly corresponds
to the JSON structure:

<details>
    <summary>Java</summary>

```java
class EventJson {
  String title;
  String begin_date;
  String begin_time;
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class EventJson(
  val title: String,
  val begin_date: String,
  val begin_time: String
)
```
</details>

And another class with the appropriate `@FromJson` and `@ToJson` methods that are telling Moshi how
to convert an `EventJson` to an `Event` and back. Now, whenever we are asking Moshi to parse a JSON
to an `Event` it will first parse it to an `EventJson` as an intermediate step. Conversely, to
serialize an `Event` Moshi will first create an `EventJson` object and then serialize that object as
usual.

<details>
    <summary>Java</summary>

```java
class EventJsonAdapter {
  @FromJson Event eventFromJson(EventJson eventJson) {
    Event event = new Event();
    event.title = eventJson.title;
    event.beginDateAndTime = eventJson.begin_date + " " + eventJson.begin_time;
    return event;
  }

  @ToJson EventJson eventToJson(Event event) {
    EventJson json = new EventJson();
    json.title = event.title;
    json.begin_date = event.beginDateAndTime.substring(0, 8);
    json.begin_time = event.beginDateAndTime.substring(9, 14);
    return json;
  }
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class EventJsonAdapter {
  @FromJson
  fun eventFromJson(eventJson: EventJson): Event {
    return Event(
      title = eventJson.title,
      beginDateAndTime = "${eventJson.begin_date} ${eventJson.begin_time}"
    )
  }

  @ToJson
  fun eventToJson(event: Event): EventJson {
    return EventJson(
      title = event.title,
      begin_date = event.beginDateAndTime.substring(0, 8),
      begin_time = event.beginDateAndTime.substring(9, 14),
    )
  }
}
```
</details>

Again we register the adapter with Moshi.

<details>
    <summary>Java</summary>

```java
Moshi moshi = new Moshi.Builder()
    .add(new EventJsonAdapter())
    .build();
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
val moshi = Moshi.Builder()
    .add(EventJsonAdapter())
    .build()
```
</details>

We can now use Moshi to parse the JSON directly to an `Event`.

<details>
    <summary>Java</summary>

```java
JsonAdapter<Event> jsonAdapter = moshi.adapter(Event.class);
Event event = jsonAdapter.fromJson(json);
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
val jsonAdapter = moshi.adapter<Event>()
val event = jsonAdapter.fromJson(json)
```
</details>

### Adapter convenience methods

Moshi provides a number of convenience methods for `JsonAdapter` objects:
- `nullSafe()`
- `nonNull()`
- `lenient()`
- `failOnUnknown()`
- `indent()`
- `serializeNulls()`

These factory methods wrap an existing `JsonAdapter` into additional functionality.
For example, if you have an adapter that doesn't support nullable values, you can use `nullSafe()` to make it null safe:

<details>
    <summary>Java</summary>

```java
String dateJson = "\"2018-11-26T11:04:19.342668Z\"";
String nullDateJson = "null";

// Hypothetical IsoDateDapter, doesn't support null by default
JsonAdapter<Date> adapter = new IsoDateDapter();

Date date = adapter.fromJson(dateJson);
System.out.println(date); // Mon Nov 26 12:04:19 CET 2018

Date nullDate = adapter.fromJson(nullDateJson);
// Exception, com.squareup.moshi.JsonDataException: Expected a string but was NULL at path $

Date nullDate = adapter.nullSafe().fromJson(nullDateJson);
System.out.println(nullDate); // null
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
val dateJson = "\"2018-11-26T11:04:19.342668Z\""
val nullDateJson = "null"

// Hypothetical IsoDateDapter, doesn't support null by default
val adapter: JsonAdapter<Date> = IsoDateDapter()

val date = adapter.fromJson(dateJson)
println(date) // Mon Nov 26 12:04:19 CET 2018

val nullDate = adapter.fromJson(nullDateJson)
// Exception, com.squareup.moshi.JsonDataException: Expected a string but was NULL at path $

val nullDate = adapter.nullSafe().fromJson(nullDateJson)
println(nullDate) // null
```
</details>

In contrast to `nullSafe()` there is `nonNull()` to make an adapter refuse null values. Refer to the Moshi JavaDoc for details on the various methods.

### Parse JSON Arrays

Say we have a JSON string of this structure:

```json
[
  {
    "rank": "4",
    "suit": "CLUBS"
  },
  {
    "rank": "A",
    "suit": "HEARTS"
  }
]
```

We can now use Moshi to parse the JSON string into a `List<Card>`.

<details>
    <summary>Java</summary>

```java
String cardsJsonResponse = ...;
Type type = Types.newParameterizedType(List.class, Card.class);
JsonAdapter<List<Card>> adapter = moshi.adapter(type);
List<Card> cards = adapter.fromJson(cardsJsonResponse);
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
val cardsJsonResponse: String = ...
// We can just use a reified extension!
val adapter = moshi.adapter<List<Card>>()
val cards: List<Card> = adapter.fromJson(cardsJsonResponse)
```
</details>

### Fails Gracefully

Automatic databinding almost feels like magic. But unlike the black magic that typically accompanies
reflection, Moshi is designed to help you out when things go wrong.

```
JsonDataException: Expected one of [CLUBS, DIAMONDS, HEARTS, SPADES] but was ANCHOR at path $.visible_cards[2].suit
  at com.squareup.moshi.JsonAdapters$11.fromJson(JsonAdapters.java:188)
  at com.squareup.moshi.JsonAdapters$11.fromJson(JsonAdapters.java:180)
  ...
```

Moshi always throws a standard `java.io.IOException` if there is an error reading the JSON document,
or if it is malformed. It throws a `JsonDataException` if the JSON document is well-formed, but
doesn’t match the expected format.

### Built on Okio

Moshi uses [Okio][okio] for simple and powerful I/O. It’s a fine complement to [OkHttp][okhttp],
which can share buffer segments for maximum efficiency.

### Borrows from Gson

Moshi uses the same streaming and binding mechanisms as [Gson][gson]. If you’re a Gson user you’ll
find Moshi works similarly. If you try Moshi and don’t love it, you can even migrate to Gson without
much violence!

But the two libraries have a few important differences:

 * **Moshi has fewer built-in type adapters.** For example, you need to configure your own date
   adapter. Most binding libraries will encode whatever you throw at them. Moshi refuses to
   serialize platform types (`java.*`, `javax.*`, and `android.*`) without a user-provided type
   adapter. This is intended to prevent you from accidentally locking yourself to a specific JDK or
   Android release.
 * **Moshi is less configurable.** There’s no field naming strategy, versioning, instance creators,
   or long serialization policy. Instead of naming a field `visibleCards` and using a policy class
   to convert that to `visible_cards`, Moshi wants you to just name the field `visible_cards` as it
   appears in the JSON.
 * **Moshi doesn’t have a `JsonElement` model.** Instead it just uses built-in types like `List` and
   `Map`.
 * **No HTML-safe escaping.** Gson encodes `=` as `\u003d` by default so that it can be safely
   encoded in HTML without additional escaping. Moshi encodes it naturally (as `=`) and assumes that
   the HTML encoder – if there is one – will do its job.

### Custom field names with @Json

Moshi works best when your JSON objects and Java or Kotlin classes have the same structure. But when they
don't, Moshi has annotations to customize data binding.

Use `@Json` to specify how Java fields or Kotlin properties map to JSON names. This is necessary when the JSON name
contains spaces or other characters that aren’t permitted in Java field or Kotlin property names. For example, this
JSON has a field name containing a space:

```json
{
  "username": "jesse",
  "lucky number": 32
}
```

With `@Json` its corresponding Java or Kotlin class is easy:

<details>
    <summary>Java</summary>

```java
class Player {
  String username;
  @Json(name = "lucky number") int luckyNumber;

  ...
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class Player {
  val username: String
  @Json(name = "lucky number") val luckyNumber: Int

  ...
}
```
</details>

Because JSON field names are always defined with their Java or Kotlin fields, Moshi makes it easy to find
fields when navigating between Java or Koltin and JSON.

### Alternate type adapters with @JsonQualifier

Use `@JsonQualifier` to customize how a type is encoded for some fields without changing its
encoding everywhere. This works similarly to the qualifier annotations in dependency injection
tools like Dagger and Guice.

Here’s a JSON message with two integers and a color:

```json
{
  "width": 1024,
  "height": 768,
  "color": "#ff0000"
}
```

By convention, Android programs also use `int` for colors:

<details>
    <summary>Java</summary>

```java
class Rectangle {
  int width;
  int height;
  int color;
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class Rectangle(
  val width: Int,
  val height: Int,
  val color: Int
)
```
</details>

But if we encoded the above Java or Kotlin class as JSON, the color isn't encoded properly!

```json
{
  "width": 1024,
  "height": 768,
  "color": 16711680
}
```

The fix is to define a qualifier annotation, itself annotated `@JsonQualifier`:

<details>
    <summary>Java</summary>

```java
@Retention(RUNTIME)
@JsonQualifier
public @interface HexColor {
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
@Retention(RUNTIME)
@JsonQualifier
annotation class HexColor
```
</details>


Next apply this `@HexColor` annotation to the appropriate field:

<details>
    <summary>Java</summary>

```java
class Rectangle {
  int width;
  int height;
  @HexColor int color;
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class Rectangle(
  val width: Int,
  val height: Int,
  @HexColor val color: Int
)
```
</details>

And finally define a type adapter to handle it:

<details>
    <summary>Java</summary>

```java
/** Converts strings like #ff0000 to the corresponding color ints. */
class ColorAdapter {
  @ToJson String toJson(@HexColor int rgb) {
    return String.format("#%06x", rgb);
  }

  @FromJson @HexColor int fromJson(String rgb) {
    return Integer.parseInt(rgb.substring(1), 16);
  }
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
/** Converts strings like #ff0000 to the corresponding color ints.  */
class ColorAdapter {
  @ToJson fun toJson(@HexColor rgb: Int): String {
    return "#%06x".format(rgb)
  }

  @FromJson @HexColor fun fromJson(rgb: String): Int {
    return rgb.substring(1).toInt(16)
  }
}
```
</details>

Use `@JsonQualifier` when you need different JSON encodings for the same type. Most programs
shouldn’t need this `@JsonQualifier`, but it’s very handy for those that do.

### Omitting fields

Some models declare fields that shouldn’t be included in JSON. For example, suppose our blackjack
hand has a `total` field with the sum of the cards:

<details>
    <summary>Java</summary>

```java
public final class BlackjackHand {
  private int total;

  ...
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class BlackjackHand(
  private val total: Int,

  ...
)
```
</details>

By default, all fields are emitted when encoding JSON, and all fields are accepted when decoding
JSON. Prevent a field from being included by annotating them with `@Json(ignore = true)`.

<details>
    <summary>Java</summary>

```java
public final class BlackjackHand {
  @Json(ignore = true)
  private int total;

  ...
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class BlackjackHand(...) {
  @Json(ignore = true)
  var total: Int = 0

  ...
}
```
</details>

These fields are omitted when writing JSON. When reading JSON, the field is skipped even if the
JSON contains a value for the field. Instead, it will get a default value. In Kotlin, these fields
_must_ have a default value if they are in the primary constructor.

Note that you can also use Java’s `transient` keyword or Kotlin's `@Transient` annotation on these fields
for the same effect.

### Default Values & Constructors

When reading JSON that is missing a field, Moshi relies on the Java or Kotlin or Android runtime to assign
the field’s value. Which value it uses depends on whether the class has a no-arguments constructor.

If the class has a no-arguments constructor, Moshi will call that constructor and whatever value
it assigns will be used. For example, because this class has a no-arguments constructor the `total`
field is initialized to `-1`.

Note: This section only applies to Java reflections.

```java
public final class BlackjackHand {
  private int total = -1;
  ...

  private BlackjackHand() {
  }

  public BlackjackHand(Card hidden_card, List<Card> visible_cards) {
    ...
  }
}
```

If the class doesn’t have a no-arguments constructor, Moshi can’t assign the field’s default value,
**even if it’s specified in the field declaration**. Instead, the field’s default is always `0` for
numbers, `false` for booleans, and `null` for references. In this example, the default value of
`total` is `0`!


```java
public final class BlackjackHand {
  private int total = -1;
  ...

  public BlackjackHand(Card hidden_card, List<Card> visible_cards) {
    ...
  }
}
```

This is surprising and is a potential source of bugs! For this reason consider defining a
no-arguments constructor in classes that you use with Moshi, using `@SuppressWarnings("unused")` to
prevent it from being inadvertently deleted later:


```java
public final class BlackjackHand {
  private int total = -1;
  ...

  @SuppressWarnings("unused") // Moshi uses this!
  private BlackjackHand() {
  }

  public BlackjackHand(Card hidden_card, List<Card> visible_cards) {
    ...
  }
}
```

### Composing Adapters

In some situations Moshi's default Java-to-JSON conversion isn't sufficient. You can compose
adapters to build upon the standard conversion.

In this example, we turn serialize nulls, then delegate to the built-in adapter:

<details>
    <summary>Java</summary>

```java
class TournamentWithNullsAdapter {
  @ToJson void toJson(JsonWriter writer, Tournament tournament,
      JsonAdapter<Tournament> delegate) throws IOException {
    boolean wasSerializeNulls = writer.getSerializeNulls();
    writer.setSerializeNulls(true);
    try {
      delegate.toJson(writer, tournament);
    } finally {
      writer.setLenient(wasSerializeNulls);
    }
  }
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class TournamentWithNullsAdapter {
  @ToJson fun toJson(writer: JsonWriter, tournament: Tournament?,
    delegate: JsonAdapter<Tournament?>) {
    val wasSerializeNulls: Boolean = writer.getSerializeNulls()
    writer.setSerializeNulls(true)
    try {
      delegate.toJson(writer, tournament)
    } finally {
      writer.setLenient(wasSerializeNulls)
    }
  }
}
```
</details>


When we use this to serialize a tournament, nulls are written! But nulls elsewhere in our JSON
document are skipped as usual.

Moshi has a powerful composition system in its `JsonAdapter.Factory` interface. We can hook in to
the encoding and decoding process for any type, even without knowing about the types beforehand. In
this example, we customize types annotated `@AlwaysSerializeNulls`, which an annotation we create,
not built-in to Moshi:

<details>
    <summary>Java</summary>

```java
@Target(TYPE)
@Retention(RUNTIME)
public @interface AlwaysSerializeNulls {}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
@Target(TYPE)
@Retention(RUNTIME)
annotation class AlwaysSerializeNulls
```
</details>

<details>
    <summary>Java</summary>

```java
@AlwaysSerializeNulls
static class Car {
  String make;
  String model;
  String color;
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
@AlwaysSerializeNulls
class Car(
  val make: String?,
  val model: String?,
  val color: String?
)
```
</details>

Each `JsonAdapter.Factory` interface is invoked by `Moshi` when it needs to build an adapter for a
user's type. The factory either returns an adapter to use, or null if it doesn't apply to the
requested type. In our case we match all classes that have our annotation.

<details>
    <summary>Java</summary>

```java
static class AlwaysSerializeNullsFactory implements JsonAdapter.Factory {
  @Override public JsonAdapter<?> create(
      Type type, Set<? extends Annotation> annotations, Moshi moshi) {
    Class<?> rawType = Types.getRawType(type);
    if (!rawType.isAnnotationPresent(AlwaysSerializeNulls.class)) {
      return null;
    }

    JsonAdapter<Object> delegate = moshi.nextAdapter(this, type, annotations);
    return delegate.serializeNulls();
  }
}
```
</details>

<details open>
    <summary>Kotlin</summary>

```kotlin
class AlwaysSerializeNullsFactory : JsonAdapter.Factory {
  override fun create(type: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<*>? {
    val rawType: Class<*> = type.rawType
    if (!rawType.isAnnotationPresent(AlwaysSerializeNulls::class.java)) {
      return null
    }
    val delegate: JsonAdapter<Any> = moshi.nextAdapter(this, type, annotations)
    return delegate.serializeNulls()
  }
}
```
</details>

After determining that it applies, the factory looks up Moshi's built-in adapter by calling
`Moshi.nextAdapter()`. This is key to the composition mechanism: adapters delegate to each other!
The composition in this example is simple: it applies the `serializeNulls()` transform on the
delegate.

Composing adapters can be very sophisticated:

 * An adapter could transform the input object before it is JSON-encoded. A string could be
   trimmed or truncated; a value object could be simplified or normalized.

 * An adapter could repair the output object after it is JSON-decoded. It could fill-in missing
   data or discard unwanted data.

 * The JSON could be given extra structure, such as wrapping values in objects or arrays.

Moshi is itself built on the pattern of repeatedly composing adapters. For example, Moshi's built-in
adapter for `List<T>` delegates to the adapter of `T`, and calls it repeatedly.

### Precedence

Moshi's composition mechanism tries to find the best adapter for each type. It starts with the first
adapter or factory registered with `Moshi.Builder.add()`, and proceeds until it finds an adapter for
the target type.

If a type can be matched multiple adapters, the earliest one wins.

To register an adapter at the end of the list, use `Moshi.Builder.addLast()` instead. This is most
useful when registering general-purpose adapters, such as the `KotlinJsonAdapterFactory` below.

Kotlin
------

Moshi is a great JSON library for Kotlin. It understands Kotlin’s non-nullable types and default
parameter values. When you use Kotlin with Moshi you may use reflection, codegen, or both.

#### Reflection

The reflection adapter uses Kotlin’s reflection library to convert your Kotlin classes to and from
JSON. Enable it by adding the `KotlinJsonAdapterFactory` to your `Moshi.Builder`:

```kotlin
val moshi = Moshi.Builder()
    .addLast(KotlinJsonAdapterFactory())
    .build()
```

Moshi’s adapters are ordered by precedence, so you should use `addLast()` with
`KotlinJsonAdapterFactory`, and `add()` with your custom adapters.

The reflection adapter requires the following additional dependency:

```xml
<dependency>
  <groupId>com.squareup.moshi</groupId>
  <artifactId>moshi-kotlin</artifactId>
  <version>1.15.2</version>
</dependency>
```

```kotlin
implementation("com.squareup.moshi:moshi-kotlin:2.0.0-alpha.1")
```

Note that the reflection adapter transitively depends on the `kotlin-reflect` library which is a
2.5 MiB .jar file.

#### Codegen

Moshi’s Kotlin codegen support can be used as a Kotlin SymbolProcessor ([KSP][ksp]).
It generates a small and fast adapter for each of your Kotlin classes at compile-time. Enable it by annotating
each class that you want to encode as JSON:

```kotlin
@JsonClass(generateAdapter = true)
data class BlackjackHand(
  val hidden_card: Card,
  val visible_cards: List<Card>
)
```

The codegen adapter requires that your Kotlin types and their properties be either `internal` or
`public` (this is Kotlin’s default visibility).

Kotlin codegen has no additional runtime dependency. You’ll need to enable kapt or KSP and then
add the following to your build to enable the annotation processor:

<details open>
    <summary>KSP</summary>

```kotlin
plugins {
  id("com.google.devtools.ksp") version "2.3.4" // Or latest version of KSP
}

dependencies {
  ksp("com.squareup.moshi:moshi-kotlin-codegen:2.0.0-alpha.1")
}

```
</details>

#### Limitations

If your Kotlin class has a superclass, it must also be a Kotlin class. Neither reflection or codegen
support Kotlin types with Java supertypes or Java types with Kotlin supertypes. If you need to
convert such classes to JSON you must create a custom type adapter.

The JSON encoding of Kotlin types is the same whether using reflection or codegen. Prefer codegen
for better performance and to avoid the `kotlin-reflect` dependency; prefer reflection to convert
both private and protected properties. If you have configured both, generated adapters will be used
on types that are annotated `@JsonClass(generateAdapter = true)`.

Download
--------

Download [the latest JAR][dl] or depend via Maven:

```xml
<dependency>
  <groupId>com.squareup.moshi</groupId>
  <artifactId>moshi</artifactId>
  <version>1.15.2</version>
</dependency>
```
or Gradle:
```kotlin
implementation("com.squareup.moshi:moshi:2.0.0-alpha.1")
```

Snapshots of the development version are available in [the Central Portal Snapshots repository][snap].


R8 / ProGuard
--------

Moshi contains minimally required rules for its own internals to work without need for consumers to embed their own. However if you are using reflective serialization and R8 or ProGuard, you must add keep rules in your proguard configuration file for your reflectively serialized classes.

#### Enums

Annotate enums with `@JsonClass(generateAdapter = false)` to prevent them from being removed/obfuscated from your code by R8/ProGuard.

License
--------

    Copyright 2015 Square, Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.


 [dl]: https://search.maven.org/classic/remote_content?g=com.squareup.moshi&a=moshi&v=LATEST
 [snap]: https://central.sonatype.com/repository/maven-snapshots/
 [okio]: https://github.com/square/okio/
 [okhttp]: https://github.com/square/okhttp/
 [gson]: https://github.com/google/gson/
 [javadoc]: https://square.github.io/moshi/1.x/moshi/
 [ksp]: https://github.com/google/ksp


================================================
FILE: build.gradle.kts
================================================
import com.diffplug.gradle.spotless.JavaExtension
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import java.net.URI
import org.jetbrains.dokka.gradle.DokkaExtension
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

buildscript {
  dependencies {
    val kotlinVersion = System.getenv("MOSHI_KOTLIN_VERSION") ?: libs.versions.kotlin.get()
    val kspVersion = System.getenv("MOSHI_KSP_VERSION") ?: libs.versions.ksp.get()
    classpath(kotlin("gradle-plugin", version = kotlinVersion))
    classpath("com.google.devtools.ksp:symbol-processing-gradle-plugin:$kspVersion")
  }
}

plugins {
  alias(libs.plugins.mavenPublish) apply false
  alias(libs.plugins.dokka)
  alias(libs.plugins.spotless)
  alias(libs.plugins.japicmp) apply false
  alias(libs.plugins.ksp) apply false
}

allprojects {
  group = "com.squareup.moshi"
  version = project.property("VERSION_NAME") as String

  repositories { mavenCentral() }
}

spotless {
  format("misc") {
    target("*.md", ".gitignore")
    trimTrailingWhitespace()
    leadingTabsToSpaces(2)
    endWithNewline()
  }
  val configureCommonJavaFormat: JavaExtension.() -> Unit = {
    googleJavaFormat(libs.googleJavaFormat.get().version)
  }
  java {
    configureCommonJavaFormat()
    target("**/*.java")
    targetExclude("**/build/**")
  }
  kotlin {
    ktfmt(libs.ktfmt.get().version).googleStyle()
    target("**/*.kt")
    trimTrailingWhitespace()
    endWithNewline()
    targetExclude("**/Dependencies.kt", "**/build/**")
  }
  kotlinGradle {
    ktfmt(libs.ktfmt.get().version).googleStyle()
    target("**/*.gradle.kts")
    trimTrailingWhitespace()
    endWithNewline()
  }
}

subprojects {
  // Apply with "java" instead of just "java-library" so kotlin projects get it too
  pluginManager.withPlugin("java") {
    configure<JavaPluginExtension> {
      toolchain { languageVersion.set(libs.versions.jdk.map(JavaLanguageVersion::of)) }
    }
    if (project.name != "records-tests") {
      tasks.withType<JavaCompile>().configureEach { options.release.set(8) }
    }
  }

  pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
    tasks.withType<KotlinCompile>().configureEach {
      compilerOptions {
        progressiveMode.set(true)
        jvmTarget.set(JvmTarget.fromTarget(libs.versions.jvmTarget.get()))
      }
    }

    configure<KotlinProjectExtension> {
      if (project.name != "examples") {
        explicitApi()
      }
    }
  }
}

dependencies {
  dokka(project(":moshi"))
  dokka(project(":moshi-adapters"))
  dokka(project(":moshi-kotlin"))
  dokka(project(":moshi-kotlin-codegen"))
}

dokka { dokkaPublications.html { outputDirectory.set(layout.projectDirectory.dir("docs/2.x")) } }

subprojects {
  plugins.withId("org.jetbrains.dokka") {
    configure<DokkaExtension> {
      basePublicationsDirectory.set(layout.buildDirectory.dir("dokkaDir"))
      dokkaSourceSets.configureEach {
        skipDeprecated.set(true)
        reportUndocumented.set(true)
        jdkVersion.set(8)
        perPackageOption {
          matchingRegex.set("com\\.squareup\\.moshi\\.internal.*")
          suppress.set(true)
        }
        externalDocumentationLinks.register("Okio") {
          packageListUrl("https://square.github.io/okio/3.x/okio/okio/package-list")
          url("https://square.github.io/okio/3.x/okio")
        }
        sourceLink {
          localDirectory.set(layout.projectDirectory.dir("src"))
          val relPath =
            rootProject.isolated.projectDirectory.asFile.toPath().relativize(projectDir.toPath())
          remoteUrl("https://github.com/square/moshi/tree/main/$relPath/src")
          remoteLineSuffix.set("#L")
        }
      }
    }
  }

  plugins.withId("com.vanniktech.maven.publish") {
    configure<PublishingExtension> {
      repositories {
        /*
         * Want to push to an internal repository for testing?
         * Set the following properties in ~/.gradle/gradle.properties.
         *
         * internalUrl=YOUR_INTERNAL_URL
         * internalUsername=YOUR_USERNAME
         * internalPassword=YOUR_PASSWORD
         *
         * Then run the following command to publish a new internal release:
         *
         * ./gradlew publishAllPublicationsToInternalRepository -DRELEASE_SIGNING_ENABLED=false
         */
        val internalUrl = providers.gradleProperty("internalUrl").orNull
        if (internalUrl != null) {
          maven {
            name = "internal"
            url = URI(internalUrl)
            credentials {
              username = providers.gradleProperty("internalUsername").get()
              password = providers.gradleProperty("internalPassword").get()
            }
          }
        }
      }
    }
    configure<MavenPublishBaseExtension> {
      publishToMavenCentral(automaticRelease = true)
      signAllPublications()
      pom {
        description.set("A modern JSON API for Android and Java")
        name.set(project.name)
        url.set("https://github.com/square/moshi/")
        licenses {
          license {
            name.set("The Apache Software License, Version 2.0")
            url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
            distribution.set("repo")
          }
        }
        scm {
          url.set("https://github.com/square/moshi/")
          connection.set("scm:git:git://github.com/square/moshi.git")
          developerConnection.set("scm:git:ssh://git@github.com/square/moshi.git")
        }
        developers {
          developer {
            id.set("square")
            name.set("Square, Inc.")
          }
        }
      }
    }
  }
}


================================================
FILE: examples/build.gradle.kts
================================================
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
  kotlin("jvm")
  alias(libs.plugins.ksp)
}

dependencies {
  ksp(project(":moshi-kotlin-codegen"))
  compileOnly(libs.jsr305)
  implementation(project(":moshi"))
  implementation(project(":moshi-adapters"))
}

tasks.withType<KotlinCompile>().configureEach {
  compilerOptions { freeCompilerArgs.add("-opt-in=kotlin.ExperimentalStdlibApi") }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/ByteStrings.java
================================================
/*
 * Copyright (C) 2018 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import java.io.IOException;
import okio.ByteString;

public final class ByteStrings {
  public void run() throws Exception {
    String json = "\"TW9zaGksIE9saXZlLCBXaGl0ZSBDaGluPw\"";

    Moshi moshi = new Moshi.Builder().add(ByteString.class, new Base64ByteStringAdapter()).build();
    JsonAdapter<ByteString> jsonAdapter = moshi.adapter(ByteString.class);

    ByteString byteString = jsonAdapter.fromJson(json);
    System.out.println(byteString);
  }

  /**
   * Formats byte strings using <a href="http://www.ietf.org/rfc/rfc2045.txt">Base64</a>. No line
   * breaks or whitespace is included in the encoded form.
   */
  public final class Base64ByteStringAdapter extends JsonAdapter<ByteString> {
    @Override
    public ByteString fromJson(JsonReader reader) throws IOException {
      String base64 = reader.nextString();
      return ByteString.decodeBase64(base64);
    }

    @Override
    public void toJson(JsonWriter writer, ByteString value) throws IOException {
      String string = value.base64();
      writer.value(string);
    }
  }

  public static void main(String[] args) throws Exception {
    new ByteStrings().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/CardAdapter.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.ToJson;
import com.squareup.moshi.recipes.models.Card;
import com.squareup.moshi.recipes.models.Suit;

public final class CardAdapter {
  @ToJson
  String toJson(Card card) {
    return card.rank + card.suit.name().substring(0, 1);
  }

  @FromJson
  Card fromJson(String card) {
    if (card.length() != 2) throw new JsonDataException("Unknown card: " + card);

    char rank = card.charAt(0);
    switch (card.charAt(1)) {
      case 'C':
        return new Card(rank, Suit.CLUBS);
      case 'D':
        return new Card(rank, Suit.DIAMONDS);
      case 'H':
        return new Card(rank, Suit.HEARTS);
      case 'S':
        return new Card(rank, Suit.SPADES);
      default:
        throw new JsonDataException("unknown suit: " + card);
    }
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomAdapterFactory.java
================================================
/*
 * Copyright (C) 2018 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.annotation.Nullable;

public final class CustomAdapterFactory {
  public void run() throws Exception {
    Moshi moshi = new Moshi.Builder().add(new SortedSetAdapterFactory()).build();
    JsonAdapter<SortedSet<String>> jsonAdapter =
        moshi.adapter(Types.newParameterizedType(SortedSet.class, String.class));

    TreeSet<String> model = new TreeSet<>();
    model.add("a");
    model.add("b");
    model.add("c");

    String json = jsonAdapter.toJson(model);
    System.out.println(json);
  }

  /**
   * This class composes an adapter for any element type into an adapter for a sorted set of those
   * elements. For example, given a {@code JsonAdapter<MovieTicket>}, use this to get a {@code
   * JsonAdapter<SortedSet<MovieTicket>>}. It works by looping over the input elements when both
   * reading and writing.
   */
  static final class SortedSetAdapter<T> extends JsonAdapter<SortedSet<T>> {
    private final JsonAdapter<T> elementAdapter;

    SortedSetAdapter(JsonAdapter<T> elementAdapter) {
      this.elementAdapter = elementAdapter;
    }

    @Override
    public SortedSet<T> fromJson(JsonReader reader) throws IOException {
      TreeSet<T> result = new TreeSet<>();
      reader.beginArray();
      while (reader.hasNext()) {
        result.add(elementAdapter.fromJson(reader));
      }
      reader.endArray();
      return result;
    }

    @Override
    public void toJson(JsonWriter writer, SortedSet<T> set) throws IOException {
      writer.beginArray();
      for (T element : set) {
        elementAdapter.toJson(writer, element);
      }
      writer.endArray();
    }
  }

  /**
   * Moshi asks this class to create JSON adapters. It only knows how to create JSON adapters for
   * {@code SortedSet} types, so it returns null for all other requests. When it does get a request
   * for a {@code SortedSet<X>}, it asks Moshi for an adapter of the element type {@code X} and then
   * uses that to create an adapter for the set.
   */
  static class SortedSetAdapterFactory implements JsonAdapter.Factory {
    @Override
    public @Nullable JsonAdapter<?> create(
        Type type, Set<? extends Annotation> annotations, Moshi moshi) {
      if (!annotations.isEmpty()) {
        return null; // Annotations? This factory doesn't apply.
      }

      if (!(type instanceof ParameterizedType)) {
        return null; // No type parameter? This factory doesn't apply.
      }

      ParameterizedType parameterizedType = (ParameterizedType) type;
      if (parameterizedType.getRawType() != SortedSet.class) {
        return null; // Not a sorted set? This factory doesn't apply.
      }

      Type elementType = parameterizedType.getActualTypeArguments()[0];
      JsonAdapter<Object> elementAdapter = moshi.adapter(elementType);

      return new SortedSetAdapter<>(elementAdapter).nullSafe();
    }
  }

  public static void main(String[] args) throws Exception {
    new CustomAdapterFactory().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomAdapterWithDelegate.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.FromJson;
import com.squareup.moshi.Json;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.Moshi;
import java.io.IOException;
import javax.annotation.Nullable;

public final class CustomAdapterWithDelegate {
  public void run() throws Exception {
    // We want to match any Stage that starts with 'in-progress' as Stage.IN_PROGRESS
    // and leave the rest of the enum values as to match as normal.
    Moshi moshi = new Moshi.Builder().add(new StageAdapter()).build();
    JsonAdapter<Stage> jsonAdapter = moshi.adapter(Stage.class);

    System.out.println(jsonAdapter.fromJson("\"not-started\""));
    System.out.println(jsonAdapter.fromJson("\"in-progress\""));
    System.out.println(jsonAdapter.fromJson("\"in-progress-step1\""));
  }

  public static void main(String[] args) throws Exception {
    new CustomAdapterWithDelegate().run();
  }

  private enum Stage {
    @Json(name = "not-started")
    NOT_STARTED,
    @Json(name = "in-progress")
    IN_PROGRESS,
    @Json(name = "rejected")
    REJECTED,
    @Json(name = "completed")
    COMPLETED
  }

  private static final class StageAdapter {
    @FromJson
    @Nullable
    Stage fromJson(JsonReader jsonReader, JsonAdapter<Stage> delegate) throws IOException {
      String value = jsonReader.nextString();

      Stage stage;
      if (value.startsWith("in-progress")) {
        stage = Stage.IN_PROGRESS;
      } else {
        stage = delegate.fromJsonValue(value);
      }
      return stage;
    }
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomFieldName.java
================================================
/*
 * Copyright (C) 2016 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.recipes.models.Player;

public final class CustomFieldName {
  public void run() throws Exception {
    String json = "" + "{" + "  \"username\": \"jesse\"," + "  \"lucky number\": 32" + "}\n";

    Moshi moshi = new Moshi.Builder().build();
    JsonAdapter<Player> jsonAdapter = moshi.adapter(Player.class);

    Player player = jsonAdapter.fromJson(json);
    System.out.println(player);
  }

  public static void main(String[] args) throws Exception {
    new CustomFieldName().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomQualifier.java
================================================
/*
 * Copyright (C) 2016 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonQualifier;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import java.lang.annotation.Retention;

public final class CustomQualifier {
  public void run() throws Exception {
    String json =
        ""
            + "{\n"
            + "  \"color\": \"#ff0000\",\n"
            + "  \"height\": 768,\n"
            + "  \"width\": 1024\n"
            + "}\n";

    Moshi moshi = new Moshi.Builder().add(new ColorAdapter()).build();
    JsonAdapter<Rectangle> jsonAdapter = moshi.adapter(Rectangle.class);

    Rectangle rectangle = jsonAdapter.fromJson(json);
    System.out.println(rectangle);
  }

  public static void main(String[] args) throws Exception {
    new CustomQualifier().run();
  }

  static class Rectangle {
    int width;
    int height;
    @HexColor int color;

    @Override
    public String toString() {
      return String.format("%dx%d #%06x", width, height, color);
    }
  }

  @Retention(RUNTIME)
  @JsonQualifier
  public @interface HexColor {}

  static class ColorAdapter {
    @ToJson
    String toJson(@HexColor int rgb) {
      return String.format("#%06x", rgb);
    }

    @FromJson
    @HexColor
    int fromJson(String rgb) {
      return Integer.parseInt(rgb.substring(1), 16);
    }
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomTypeAdapter.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.recipes.models.BlackjackHand;

public final class CustomTypeAdapter {
  public void run() throws Exception {
    String json =
        ""
            + "{\n"
            + "  \"hidden_card\": \"6S\",\n"
            + "  \"visible_cards\": [\n"
            + "    \"4C\",\n"
            + "    \"AH\"\n"
            + "  ]\n"
            + "}\n";

    Moshi moshi = new Moshi.Builder().add(new CardAdapter()).build();
    JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);

    BlackjackHand blackjackHand = jsonAdapter.fromJson(json);
    System.out.println(blackjackHand);
  }

  public static void main(String[] args) throws Exception {
    new CustomTypeAdapter().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/DefaultOnDataMismatchAdapter.java
================================================
/*
 * Copyright (C) 2017 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Set;
import javax.annotation.Nullable;

public final class DefaultOnDataMismatchAdapter<T> extends JsonAdapter<T> {
  private final JsonAdapter<T> delegate;
  private final T defaultValue;

  private DefaultOnDataMismatchAdapter(JsonAdapter<T> delegate, T defaultValue) {
    this.delegate = delegate;
    this.defaultValue = defaultValue;
  }

  @Override
  public T fromJson(JsonReader reader) throws IOException {
    // Use a peeked reader to leave the reader in a known state even if there's an exception.
    JsonReader peeked = reader.peekJson();
    T result;
    try {
      // Attempt to decode to the target type with the peeked reader.
      result = delegate.fromJson(peeked);
    } catch (JsonDataException e) {
      result = defaultValue;
    } finally {
      peeked.close();
    }
    // Skip the value back on the reader, no matter the state of the peeked reader.
    reader.skipValue();
    return result;
  }

  @Override
  public void toJson(JsonWriter writer, T value) throws IOException {
    delegate.toJson(writer, value);
  }

  public static <T> Factory newFactory(final Class<T> type, final T defaultValue) {
    return new Factory() {
      @Override
      public @Nullable JsonAdapter<?> create(
          Type requestedType, Set<? extends Annotation> annotations, Moshi moshi) {
        if (type != requestedType) return null;
        JsonAdapter<T> delegate = moshi.nextAdapter(this, type, annotations);
        return new DefaultOnDataMismatchAdapter<>(delegate, defaultValue);
      }
    };
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/FallbackEnum.java
================================================
/*
 * Copyright (C) 2018 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonQualifier;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import com.squareup.moshi.internal.Util;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.reflect.Type;
import java.util.Set;
import javax.annotation.Nullable;

final class FallbackEnum {
  @Retention(RUNTIME)
  @JsonQualifier
  public @interface Fallback {
    /** The enum name. */
    String value();
  }

  public static final class FallbackEnumJsonAdapter<T extends Enum<T>> extends JsonAdapter<T> {
    public static final Factory FACTORY =
        new Factory() {
          @Nullable
          @Override
          @SuppressWarnings("unchecked")
          public JsonAdapter<?> create(
              Type type, Set<? extends Annotation> annotations, Moshi moshi) {
            Class<?> rawType = Types.getRawType(type);
            if (!rawType.isEnum()) {
              return null;
            }
            if (annotations.size() != 1) {
              return null;
            }
            Annotation annotation = annotations.iterator().next();
            if (!(annotation instanceof Fallback)) {
              return null;
            }
            //noinspection rawtypes
            return new FallbackEnumJsonAdapter<>(
                (Class<? extends Enum>) rawType, ((Fallback) annotation).value());
          }
        };

    final Class<T> enumType;
    final String[] nameStrings;
    final T[] constants;
    final JsonReader.Options options;
    final T defaultValue;

    FallbackEnumJsonAdapter(Class<T> enumType, String fallbackName) {
      this.enumType = enumType;
      this.defaultValue = Enum.valueOf(enumType, fallbackName);
      try {
        constants = enumType.getEnumConstants();
        nameStrings = new String[constants.length];
        for (int i = 0; i < constants.length; i++) {
          String constantName = constants[i].name();
          nameStrings[i] = Util.jsonName(enumType.getField(constantName), constantName);
        }
        options = JsonReader.Options.of(nameStrings);
      } catch (NoSuchFieldException e) {
        throw new AssertionError(e);
      }
    }

    @Override
    public T fromJson(JsonReader reader) throws IOException {
      int index = reader.selectString(options);
      if (index != -1) return constants[index];
      reader.nextString();
      return defaultValue;
    }

    @Override
    public void toJson(JsonWriter writer, T value) throws IOException {
      writer.value(nameStrings[value.ordinal()]);
    }

    @Override
    public String toString() {
      return "JsonAdapter(" + enumType.getName() + ").defaultValue( " + defaultValue + ")";
    }
  }

  static final class Example {
    enum Transportation {
      WALKING,
      BIKING,
      TRAINS,
      PLANES
    }

    @Fallback("WALKING")
    final Transportation transportation;

    Example(Transportation transportation) {
      this.transportation = transportation;
    }

    @Override
    public String toString() {
      return transportation.toString();
    }
  }

  public static void main(String[] args) throws Exception {
    Moshi moshi = new Moshi.Builder().add(FallbackEnumJsonAdapter.FACTORY).build();
    JsonAdapter<Example> adapter = moshi.adapter(Example.class);
    System.out.println(adapter.fromJson("{\"transportation\":\"CARS\"}"));
  }

  private FallbackEnum() {}
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/FromJsonWithoutStrings.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;

public final class FromJsonWithoutStrings {
  public void run() throws Exception {
    // For some reason our JSON has date and time as separate fields. We will clean that up during
    // parsing: Moshi will first parse the JSON directly to an EventJson and from that the
    // EventJsonAdapter will create the actual Event.
    String json =
        ""
            + "{\n"
            + "  \"title\": \"Blackjack tournament\",\n"
            + "  \"begin_date\": \"20151010\",\n"
            + "  \"begin_time\": \"17:04\"\n"
            + "}\n";

    Moshi moshi = new Moshi.Builder().add(new EventJsonAdapter()).build();
    JsonAdapter<Event> jsonAdapter = moshi.adapter(Event.class);

    Event event = jsonAdapter.fromJson(json);
    System.out.println(event);
    System.out.println(jsonAdapter.toJson(event));
  }

  public static void main(String[] args) throws Exception {
    new FromJsonWithoutStrings().run();
  }

  private static final class EventJson {
    String title;
    String begin_date;
    String begin_time;
  }

  public static final class Event {
    String title;
    String beginDateAndTime;

    @Override
    public String toString() {
      return "Event{"
          + "title='"
          + title
          + '\''
          + ", beginDateAndTime='"
          + beginDateAndTime
          + '\''
          + '}';
    }
  }

  private static final class EventJsonAdapter {
    @FromJson
    Event eventFromJson(EventJson eventJson) {
      Event event = new Event();
      event.title = eventJson.title;
      event.beginDateAndTime = eventJson.begin_date + " " + eventJson.begin_time;
      return event;
    }

    @ToJson
    EventJson eventToJson(Event event) {
      EventJson json = new EventJson();
      json.title = event.title;
      json.begin_date = event.beginDateAndTime.substring(0, 8);
      json.begin_time = event.beginDateAndTime.substring(9, 14);
      return json;
    }
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/IncludeNullsForAnnotatedTypes.java
================================================
/*
 * Copyright (C) 2020 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.Type;
import java.util.Set;

public final class IncludeNullsForAnnotatedTypes {
  public void run() throws Exception {
    Moshi moshi = new Moshi.Builder().add(new AlwaysSerializeNullsFactory()).build();

    JsonAdapter<Driver> driverAdapter = moshi.adapter(Driver.class);

    Car car = new Car();
    car.make = "Ford";
    car.model = "Mach-E";
    car.color = null; // This null will show up in the JSON because Car has @AlwaysSerializeNulls.

    Driver driver = new Driver();
    driver.name = "Jesse";
    driver.emailAddress = null; // This null will be omitted.
    driver.favoriteCar = car;

    System.out.println(driverAdapter.toJson(driver));
  }

  @Target(TYPE)
  @Retention(RUNTIME)
  public @interface AlwaysSerializeNulls {}

  @AlwaysSerializeNulls
  static class Car {
    String make;
    String model;
    String color;
  }

  static class Driver {
    String name;
    String emailAddress;
    Car favoriteCar;
  }

  static class AlwaysSerializeNullsFactory implements JsonAdapter.Factory {
    @Override
    public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
      Class<?> rawType = Types.getRawType(type);
      if (!rawType.isAnnotationPresent(AlwaysSerializeNulls.class)) {
        return null;
      }
      JsonAdapter<Object> delegate = moshi.nextAdapter(this, type, annotations);
      return delegate.serializeNulls();
    }
  }

  public static void main(String[] args) throws Exception {
    new IncludeNullsForAnnotatedTypes().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/IncludeNullsForOneType.java
================================================
/*
 * Copyright (C) 2020 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter;
import com.squareup.moshi.recipes.models.Tournament;
import java.io.IOException;
import java.util.Date;

public final class IncludeNullsForOneType {
  public void run() throws Exception {
    Moshi moshi =
        new Moshi.Builder()
            .add(Date.class, new Rfc3339DateJsonAdapter())
            .add(new TournamentWithNullsAdapter())
            .build();

    JsonAdapter<Tournament> tournamentAdapter = moshi.adapter(Tournament.class);

    // Moshi normally skips nulls, but with our adapter registered they are emitted.
    Tournament withNulls = new Tournament("Waterloo Classic", null, null);
    System.out.println(tournamentAdapter.toJson(withNulls));
  }

  public static final class TournamentWithNullsAdapter {
    @ToJson
    void toJson(JsonWriter writer, Tournament tournament, JsonAdapter<Tournament> delegate)
        throws IOException {
      boolean wasSerializeNulls = writer.getSerializeNulls();
      writer.setSerializeNulls(true);
      try {
        // Once we've customized the JSON writer, we let the default JSON adapter do its job.
        delegate.toJson(writer, tournament);
      } finally {
        writer.setLenient(wasSerializeNulls);
      }
    }
  }

  public static void main(String[] args) throws Exception {
    new IncludeNullsForOneType().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/JsonString.kt
================================================
/*
 * Copyright (C) 2020 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonClass
import com.squareup.moshi.JsonQualifier
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Moshi.Builder
import com.squareup.moshi.Types
import java.lang.reflect.Type
import kotlin.annotation.AnnotationRetention.RUNTIME
import okio.BufferedSource

@JsonClass(generateAdapter = true)
data class ExampleClass(val type: Int, @JsonString val rawJson: String)

@Retention(RUNTIME) @JsonQualifier annotation class JsonString

class JsonStringJsonAdapterFactory : JsonAdapter.Factory {
  override fun create(type: Type, annotations: Set<Annotation>, moshi: Moshi): JsonAdapter<*>? {
    if (type != String::class.java) return null
    Types.nextAnnotations(annotations, JsonString::class.java) ?: return null
    return JsonStringJsonAdapter().nullSafe()
  }

  private class JsonStringJsonAdapter : JsonAdapter<String>() {
    override fun fromJson(reader: JsonReader): String =
      reader.nextSource().use(BufferedSource::readUtf8)

    override fun toJson(writer: JsonWriter, value: String) {
      writer.valueSink().use { sink -> sink.writeUtf8(value) }
    }
  }
}

fun main() {
  // language=JSON
  val json = "{\"type\":1,\"rawJson\":{\"a\":2,\"b\":3,\"c\":[1,2,3]}}"

  val moshi = Builder().add(JsonStringJsonAdapterFactory()).build()

  val example: ExampleClass = moshi.adapter<ExampleClass>().fromJson(json)

  check(example.type == 1)

  // language=JSON
  check(example.rawJson == "{\"a\":2,\"b\":3,\"c\":[1,2,3]}")
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/MultipleFormats.java
================================================
/*
 * Copyright (C) 2018 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.JsonQualifier;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import com.squareup.moshi.recipes.models.Card;
import com.squareup.moshi.recipes.models.Suit;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public final class MultipleFormats {
  public void run() throws Exception {
    Moshi moshi =
        new Moshi.Builder()
            .add(new MultipleFormatsCardAdapter())
            .add(new CardStringAdapter())
            .build();

    JsonAdapter<Card> cardAdapter = moshi.adapter(Card.class);

    // Decode cards from one format or the other.
    System.out.println(cardAdapter.fromJson("\"5D\""));
    System.out.println(cardAdapter.fromJson("{\"suit\": \"SPADES\", \"rank\": 5}"));

    // Cards are always encoded as strings.
    System.out.println(cardAdapter.toJson(new Card('5', Suit.CLUBS)));
  }

  /** Handles cards either as strings "5D" or as objects {"suit": "SPADES", "rank": 5}. */
  public final class MultipleFormatsCardAdapter {
    @ToJson
    void toJson(JsonWriter writer, Card value, @CardString JsonAdapter<Card> stringAdapter)
        throws IOException {
      stringAdapter.toJson(writer, value);
    }

    @FromJson
    Card fromJson(
        JsonReader reader,
        @CardString JsonAdapter<Card> stringAdapter,
        JsonAdapter<Card> defaultAdapter)
        throws IOException {
      if (reader.peek() == JsonReader.Token.STRING) {
        return stringAdapter.fromJson(reader);
      } else {
        return defaultAdapter.fromJson(reader);
      }
    }
  }

  /** Handles cards as strings only. */
  public final class CardStringAdapter {
    @ToJson
    String toJson(@CardString Card card) {
      return card.rank + card.suit.name().substring(0, 1);
    }

    @FromJson
    @CardString
    Card fromJson(String card) {
      if (card.length() != 2) throw new JsonDataException("Unknown card: " + card);

      char rank = card.charAt(0);
      switch (card.charAt(1)) {
        case 'C':
          return new Card(rank, Suit.CLUBS);
        case 'D':
          return new Card(rank, Suit.DIAMONDS);
        case 'H':
          return new Card(rank, Suit.HEARTS);
        case 'S':
          return new Card(rank, Suit.SPADES);
        default:
          throw new JsonDataException("unknown suit: " + card);
      }
    }
  }

  @Retention(RetentionPolicy.RUNTIME)
  @JsonQualifier
  @interface CardString {}

  public static void main(String[] args) throws Exception {
    new MultipleFormats().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/ReadAndWriteRfc3339Dates.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter;
import com.squareup.moshi.recipes.models.Tournament;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

public final class ReadAndWriteRfc3339Dates {
  public void run() throws Exception {
    Moshi moshi = new Moshi.Builder().add(Date.class, new Rfc3339DateJsonAdapter()).build();
    JsonAdapter<Tournament> jsonAdapter = moshi.adapter(Tournament.class);

    // The RFC3339 JSON adapter can read dates with a timezone offset like '-05:00'.
    String lastTournament =
        ""
            + "{"
            + "  \"location\":\"Chainsaw\","
            + "  \"name\":\"21 for 21\","
            + "  \"start\":\"2015-09-01T20:00:00-05:00\""
            + "}";
    System.out.println("Last tournament: " + jsonAdapter.fromJson(lastTournament));

    // The RFC3339 JSON adapter always writes dates with UTC, using a 'Z' suffix.
    Tournament nextTournament =
        new Tournament("Waterloo Classic", "Bauer Kitchen", newDate(2015, 10, 1, 20, -5));
    System.out.println("Next tournament JSON: " + jsonAdapter.toJson(nextTournament));
  }

  public static void main(String[] args) throws Exception {
    new ReadAndWriteRfc3339Dates().run();
  }

  private Date newDate(int year, int month, int day, int hour, int offset) {
    Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
    calendar.set(year, month - 1, day, hour, 0, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return new Date(calendar.getTimeInMillis() - TimeUnit.HOURS.toMillis(offset));
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/ReadJson.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.recipes.models.BlackjackHand;

public final class ReadJson {
  public void run() throws Exception {
    String json =
        ""
            + "{\n"
            + "  \"hidden_card\": {\n"
            + "    \"rank\": \"6\",\n"
            + "    \"suit\": \"SPADES\"\n"
            + "  },\n"
            + "  \"visible_cards\": [\n"
            + "    {\n"
            + "      \"rank\": \"4\",\n"
            + "      \"suit\": \"CLUBS\"\n"
            + "    },\n"
            + "    {\n"
            + "      \"rank\": \"A\",\n"
            + "      \"suit\": \"HEARTS\"\n"
            + "    }\n"
            + "  ]\n"
            + "}\n";

    Moshi moshi = new Moshi.Builder().build();
    JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);

    BlackjackHand blackjackHand = jsonAdapter.fromJson(json);
    System.out.println(blackjackHand);
  }

  public static void main(String[] args) throws Exception {
    new ReadJson().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/ReadJsonList.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import com.squareup.moshi.recipes.models.Card;
import java.lang.reflect.Type;
import java.util.List;

public final class ReadJsonList {
  public void run() throws Exception {
    String json =
        ""
            + "[\n"
            + "  {\n"
            + "    \"rank\": \"4\",\n"
            + "    \"suit\": \"CLUBS\"\n"
            + "  },\n"
            + "  {\n"
            + "    \"rank\": \"A\",\n"
            + "    \"suit\": \"HEARTS\"\n"
            + "  },\n"
            + "  {\n"
            + "    \"rank\": \"J\",\n"
            + "    \"suit\": \"SPADES\"\n"
            + "  }\n"
            + "]";

    Moshi moshi = new Moshi.Builder().build();

    Type listOfCardsType = Types.newParameterizedType(List.class, Card.class);
    JsonAdapter<List<Card>> jsonAdapter = moshi.adapter(listOfCardsType);

    List<Card> cards = jsonAdapter.fromJson(json);
    System.out.println(cards);
  }

  public static void main(String[] args) throws Exception {
    new ReadJsonList().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/ReadJsonListKt.kt
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes

import com.squareup.moshi.Moshi
import com.squareup.moshi.adapter
import com.squareup.moshi.recipes.models.Card

class ReadJsonListKt {

  // language=JSON
  private val jsonString =
    """
    [{"rank": "4",
       "suit": "CLUBS"
     },
     {"rank": "A",
      "suit": "HEARTS"
      },
     {"rank": "J",
      "suit": "SPADES"
     }]
    """
      .trimIndent()

  fun readJsonList() {
    val jsonAdapter = Moshi.Builder().build().adapter<List<Card>>()
    val cards = jsonAdapter.fromJson(jsonString)
    println(cards)
    cards[0].run {
      println(rank)
      println(suit)
    }
  }
}

fun main() {
  ReadJsonListKt().readJsonList()
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/RecoverFromTypeMismatch.java
================================================
/*
 * Copyright (C) 2017 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import com.squareup.moshi.recipes.models.Suit;
import java.util.List;

public final class RecoverFromTypeMismatch {
  public void run() throws Exception {
    String json = "[\"DIAMONDS\", \"STARS\", \"HEARTS\"]";

    Moshi moshi =
        new Moshi.Builder()
            .add(DefaultOnDataMismatchAdapter.newFactory(Suit.class, Suit.CLUBS))
            .build();
    JsonAdapter<List<Suit>> jsonAdapter =
        moshi.adapter(Types.newParameterizedType(List.class, Suit.class));

    List<Suit> suits = jsonAdapter.fromJson(json);
    System.out.println(suits);
  }

  public static void main(String[] args) throws Exception {
    new RecoverFromTypeMismatch().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/Unwrap.java
================================================
/*
 * Copyright (C) 2017 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonQualifier;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import com.squareup.moshi.recipes.Unwrap.EnvelopeJsonAdapter.Enveloped;
import com.squareup.moshi.recipes.models.Card;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.reflect.Type;
import java.util.Set;
import javax.annotation.Nullable;

final class Unwrap {
  private Unwrap() {}

  public static void main(String[] args) throws Exception {
    String json =
        ""
            + "{\"data\":"
            + "  {\n"
            + "    \"rank\": \"4\",\n"
            + "    \"suit\": \"CLUBS\"\n"
            + "  }"
            + "}";
    Moshi moshi = new Moshi.Builder().add(EnvelopeJsonAdapter.FACTORY).build();
    JsonAdapter<Card> adapter = moshi.adapter(Card.class, Enveloped.class);
    Card out = adapter.fromJson(json);
    System.out.println(out);
  }

  public static final class EnvelopeJsonAdapter extends JsonAdapter<Object> {
    public static final JsonAdapter.Factory FACTORY =
        new Factory() {
          @Override
          public @Nullable JsonAdapter<?> create(
              Type type, Set<? extends Annotation> annotations, Moshi moshi) {
            Set<? extends Annotation> delegateAnnotations =
                Types.nextAnnotations(annotations, Enveloped.class);
            if (delegateAnnotations == null) {
              return null;
            }
            Type envelope =
                Types.newParameterizedTypeWithOwner(
                    EnvelopeJsonAdapter.class, Envelope.class, type);
            JsonAdapter<Envelope<?>> delegate =
                moshi.nextAdapter(this, envelope, delegateAnnotations);
            return new EnvelopeJsonAdapter(delegate);
          }
        };

    @Retention(RUNTIME)
    @JsonQualifier
    public @interface Enveloped {}

    private static final class Envelope<T> {
      final T data;

      Envelope(T data) {
        this.data = data;
      }
    }

    private final JsonAdapter<Envelope<?>> delegate;

    EnvelopeJsonAdapter(JsonAdapter<Envelope<?>> delegate) {
      this.delegate = delegate;
    }

    @Override
    public Object fromJson(JsonReader reader) throws IOException {
      return delegate.fromJson(reader).data;
    }

    @Override
    public void toJson(JsonWriter writer, Object value) throws IOException {
      delegate.toJson(writer, new Envelope<>(value));
    }
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/WriteJson.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes;

import static com.squareup.moshi.recipes.models.Suit.CLUBS;
import static com.squareup.moshi.recipes.models.Suit.HEARTS;
import static com.squareup.moshi.recipes.models.Suit.SPADES;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.recipes.models.BlackjackHand;
import com.squareup.moshi.recipes.models.Card;
import java.util.Arrays;

public final class WriteJson {
  public void run() throws Exception {
    BlackjackHand blackjackHand =
        new BlackjackHand(
            new Card('6', SPADES), Arrays.asList(new Card('4', CLUBS), new Card('A', HEARTS)));

    Moshi moshi = new Moshi.Builder().build();
    JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);

    String json = jsonAdapter.toJson(blackjackHand);
    System.out.println(json);
  }

  public static void main(String[] args) throws Exception {
    new WriteJson().run();
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/models/BlackjackHand.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes.models;

import java.util.List;

public final class BlackjackHand {
  public final Card hidden_card;
  public final List<Card> visible_cards;

  public BlackjackHand(Card hiddenCard, List<Card> visibleCards) {
    this.hidden_card = hiddenCard;
    this.visible_cards = visibleCards;
  }

  @Override
  public String toString() {
    return "hidden=" + hidden_card + ",visible=" + visible_cards;
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/models/Card.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes.models;

public final class Card {
  public final char rank;
  public final Suit suit;

  public Card(char rank, Suit suit) {
    this.rank = rank;
    this.suit = suit;
  }

  @Override
  public String toString() {
    return String.format("%s%s", rank, suit);
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/models/Player.java
================================================
/*
 * Copyright (C) 2016 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes.models;

import com.squareup.moshi.Json;

public final class Player {
  public final String username;
  public final @Json(name = "lucky number") int luckyNumber;

  public Player(String username, int luckyNumber) {
    this.username = username;
    this.luckyNumber = luckyNumber;
  }

  @Override
  public String toString() {
    return username + " gets lucky with " + luckyNumber;
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/models/Suit.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes.models;

public enum Suit {
  CLUBS,
  DIAMONDS,
  HEARTS,
  SPADES;

  @Override
  public String toString() {
    return name().substring(0, 1);
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/models/Tournament.java
================================================
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.recipes.models;

import java.util.Date;

public final class Tournament {
  public final String name;
  public final String location;
  public final Date start;

  public Tournament(String name, String location, Date start) {
    this.name = name;
    this.location = location;
    this.start = start;
  }

  @Override
  public String toString() {
    return name + " at " + location + " on " + start;
  }
}


================================================
FILE: examples/src/main/java/com/squareup/moshi/recipes/package-info.java
================================================
/** Moshi code samples. */
@javax.annotation.ParametersAreNonnullByDefault
package com.squareup.moshi.recipes;


================================================
FILE: gradle/libs.versions.toml
================================================
[versions]
autoService = "1.1.1"
jdk = "21"
jvmTarget = "1.8"
kotlin = "2.3.20"
kotlinCompileTesting = "0.12.1"
kotlinpoet = "2.2.0"
ksp = "2.3.6"

[plugins]
dokka = { id = "org.jetbrains.dokka", version = "2.1.0" }
japicmp = { id = "me.champeau.gradle.japicmp", version = "0.4.6" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.36.0" }
spotless = { id = "com.diffplug.spotless", version = "8.4.0" }

[libraries]
asm = "org.ow2.asm:asm:9.9.1"
autoCommon = "com.google.auto:auto-common:1.2.2"
autoService = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoService" }
autoService-ksp = "dev.zacsweers.autoservice:auto-service-ksp:1.2.0"
jsr305 = "com.google.code.findbugs:jsr305:3.0.2"
kotlin-annotationProcessingEmbeddable = { module = "org.jetbrains.kotlin:kotlin-annotation-processing-embeddable", version.ref = "kotlin" }
kotlin-compilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlin" }
kotlin-metadata = { module = "org.jetbrains.kotlin:kotlin-metadata-jvm", version.ref = "kotlin" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlinpoet = { module = "com.squareup:kotlinpoet", version.ref = "kotlinpoet" }
kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlinpoet" }
ksp = { module = "com.google.devtools.ksp:symbol-processing", version.ref = "ksp" }
ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" }
okio = "com.squareup.okio:okio:3.17.0"
assertj = "org.assertj:assertj-core:3.27.7"
assertk = "com.willowtreeapps.assertk:assertk:0.28.1"
junit = "junit:junit:4.13.2"
kotlinCompileTesting = { module = "dev.zacsweers.kctfork:core", version.ref = "kotlinCompileTesting" }
kotlinCompileTesting-ksp = { module = "dev.zacsweers.kctfork:ksp", version.ref ="kotlinCompileTesting" }
truth = "com.google.truth:truth:1.4.5"
googleJavaFormat = "com.google.googlejavaformat:google-java-format:1.35.0"
ktfmt = "com.facebook:ktfmt:0.62"


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists


================================================
FILE: gradle.properties
================================================
# Memory for Dokka https://github.com/Kotlin/dokka/issues/1405
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8

VERSION_NAME=2.0.0-SNAPSHOT


================================================
FILE: gradlew
================================================
#!/bin/sh

#
# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
#   Gradle start up script for POSIX generated by Gradle.
#
#   Important for running:
#
#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
#       noncompliant, but you have some other compliant shell such as ksh or
#       bash, then to run this script, type that shell name before the whole
#       command line, like:
#
#           ksh Gradle
#
#       Busybox and similar reduced shells will NOT work, because this script
#       requires all of these POSIX shell features:
#         * functions;
#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
#         * compound commands having a testable exit status, especially «case»;
#         * various built-in commands including «command», «set», and «ulimit».
#
#   Important for patching:
#
#   (2) This script targets any POSIX shell, so it avoids extensions provided
#       by Bash, Ksh, etc; in particular arrays are avoided.
#
#       The "traditional" practice of packing multiple parameters into a
#       space-separated string is a well documented source of bugs and security
#       problems, so this is (mostly) avoided, by progressively accumulating
#       options in "$@", and eventually passing that to Java.
#
#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
#       see the in-line comments for details.
#
#       There are tweaks for specific operating systems such as AIX, CygWin,
#       Darwin, MinGW, and NonStop.
#
#   (3) This script is generated from the Groovy template
#       https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
#       within the Gradle project.
#
#       You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################

# Attempt to set APP_HOME

# Resolve links: $0 may be a link
app_path=$0

# Need this for daisy-chained symlinks.
while
    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
    [ -h "$app_path" ]
do
    ls=$( ls -ld "$app_path" )
    link=${ls#*' -> '}
    case $link in             #(
      /*)   app_path=$link ;; #(
      *)    app_path=$APP_HOME$link ;;
    esac
done

# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum

warn () {
    echo "$*"
} >&2

die () {
    echo
    echo "$*"
    echo
    exit 1
} >&2

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in                #(
  CYGWIN* )         cygwin=true  ;; #(
  Darwin* )         darwin=true  ;; #(
  MSYS* | MINGW* )  msys=true    ;; #(
  NONSTOP* )        nonstop=true ;;
esac



# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD=$JAVA_HOME/jre/sh/java
    else
        JAVACMD=$JAVA_HOME/bin/java
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD=java
    if ! command -v java >/dev/null 2>&1
    then
        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
fi

# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
    case $MAX_FD in #(
      max*)
        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
        # shellcheck disable=SC2039,SC3045
        MAX_FD=$( ulimit -H -n ) ||
            warn "Could not query maximum file descriptor limit"
    esac
    case $MAX_FD in  #(
      '' | soft) :;; #(
      *)
        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
        # shellcheck disable=SC2039,SC3045
        ulimit -n "$MAX_FD" ||
            warn "Could not set maximum file descriptor limit to $MAX_FD"
    esac
fi

# Collect all arguments for the java command, stacking in reverse order:
#   * args from the command line
#   * the main class name
#   * -classpath
#   * -D...appname settings
#   * --module-path (only if needed)
#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.

# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )

    JAVACMD=$( cygpath --unix "$JAVACMD" )

    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    for arg do
        if
            case $arg in                                #(
              -*)   false ;;                            # don't mess with options #(
              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
                    [ -e "$t" ] ;;                      #(
              *)    false ;;
            esac
        then
            arg=$( cygpath --path --ignore --mixed "$arg" )
        fi
        # Roll the args list around exactly as many times as the number of
        # args, so each arg winds up back in the position where it started, but
        # possibly modified.
        #
        # NB: a `for` loop captures its iteration list before it begins, so
        # changing the positional parameters here affects neither the number of
        # iterations, nor the values presented in `arg`.
        shift                   # remove old arg
        set -- "$@" "$arg"      # push replacement arg
    done
fi


# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command:
#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
#     and any embedded shellness will be escaped.
#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
#     treated as '${Hostname}' itself on the command line.

set -- \
        "-Dorg.gradle.appname=$APP_BASE_NAME" \
        -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
        "$@"

# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
    die "xargs is not available"
fi

# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
#   set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#

eval "set -- $(
        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
        xargs -n1 |
        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
        tr '\n' ' '
    )" '"$@"'

exec "$JAVACMD" "$@"


================================================
FILE: gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem      https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute

echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

:execute
@rem Setup the command line



@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*

:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: moshi/build.gradle.kts
================================================
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
  kotlin("jvm")
  id("com.vanniktech.maven.publish")
  id("org.jetbrains.dokka")
}

kotlin.target {
  val main = compilations.getByName(MAIN_COMPILATION_NAME)
  val java16 =
    compilations.create("java16") {
      associateWith(main)
      defaultSourceSet.kotlin.srcDir("src/main/java16")
      compileJavaTaskProvider.configure { options.release = 16 }
      compileTaskProvider.configure {
        (compilerOptions as KotlinJvmCompilerOptions).jvmTarget = JvmTarget.JVM_16
      }
    }

  // Package our actual RecordJsonAdapter from java16 sources in and denote it as an MRJAR
  tasks.named<Jar>(artifactsTaskName) {
    from(java16.output) {
      into("META-INF/versions/16")
      exclude("META-INF")
    }
    manifest { attributes("Multi-Release" to "true") }
  }
}

tasks.withType<Test>().configureEach {
  // ExtendsPlatformClassWithProtectedField tests a case where we set a protected
  // ByteArrayOutputStream.buf field
  jvmArgs("--add-opens=java.base/java.io=ALL-UNNAMED")
}

tasks.withType<KotlinCompile>().configureEach {
  compilerOptions {
    freeCompilerArgs.addAll("-opt-in=kotlin.contracts.ExperimentalContracts", "-Xjvm-default=all")
    if (name.contains("test", true)) {
      freeCompilerArgs.add("-opt-in=kotlin.ExperimentalStdlibApi")
    }
  }
}

dependencies {
  compileOnly(libs.jsr305)
  api(libs.okio)

  testCompileOnly(libs.jsr305)
  testImplementation(libs.assertk)
  testImplementation(libs.junit)
  testImplementation(libs.kotlin.reflect)
  testImplementation(libs.truth)
}

tasks.withType<Jar>().configureEach {
  manifest { attributes("Automatic-Module-Name" to "com.squareup.moshi") }
}


================================================
FILE: moshi/gradle.properties
================================================
kotlin.build.archivesTaskOutputAsFriendModule=false


================================================
FILE: moshi/japicmp/build.gradle.kts
================================================
import me.champeau.gradle.japicmp.JapicmpTask

plugins {
  `java-library`
  id("me.champeau.gradle.japicmp")
}

val baseline = configurations.create("baseline")
val latest = configurations.create("latest")

dependencies {
  baseline("com.squareup.moshi:moshi:1.15.2") {
    isTransitive = false
    version { strictly("1.14.0") }
  }
  latest(project(":moshi"))
}

val japicmp =
  tasks.register<JapicmpTask>("japicmp") {
    dependsOn("jar")
    oldClasspath.from(baseline)
    newClasspath.from(latest)
    onlyBinaryIncompatibleModified.set(true)
    failOnModification.set(true)
    txtOutputFile.set(layout.buildDirectory.file("reports/japi.txt"))
    ignoreMissingClasses.set(true)
    includeSynthetic.set(true)
    classExcludes.addAll(
      // Internal.
      "com.squareup.moshi.AdapterMethodsFactory",
      "com.squareup.moshi.ClassJsonAdapter",
      "com.squareup.moshi.internal.NonNullJsonAdapter",
      "com.squareup.moshi.internal.NullSafeJsonAdapter",
      "com.squareup.moshi.internal.Util\$GenericArrayTypeImpl",
      "com.squareup.moshi.internal.Util\$ParameterizedTypeImpl",
      "com.squareup.moshi.internal.Util\$WildcardTypeImpl",
      // Package-private
      "com.squareup.moshi.RecordJsonAdapter\$ComponentBinding",
      "com.squareup.moshi.StandardJsonAdapters",
    )
    methodExcludes.addAll(
      // Was unintentionally open before
      "com.squareup.moshi.JsonAdapter#indent(java.lang.String)",
      "com.squareup.moshi.internal.Util#hasNullable(java.lang.annotation.Annotation[])",
      "com.squareup.moshi.internal.Util#jsonAnnotations(java.lang.annotation.Annotation[])",
      "com.squareup.moshi.internal.Util#jsonAnnotations(java.lang.reflect.AnnotatedElement)",
      "com.squareup.moshi.internal.Util#jsonName(java.lang.String, com.squareup.moshi.Json)",
      "com.squareup.moshi.internal.Util#jsonName(java.lang.String, java.lang.reflect.AnnotatedElement)",
      "com.squareup.moshi.internal.Util#resolve(java.lang.reflect.Type, java.lang.Class, java.lang.reflect.Type)",
      "com.squareup.moshi.internal.Util#typeAnnotatedWithAnnotations(java.lang.reflect.Type, java.util.Set)",
      "com.squareup.moshi.internal.Util#typesMatch(java.lang.reflect.Type, java.lang.reflect.Type)",
    )
    fieldExcludes.addAll(
      // False-positive, class is not public anyway
      "com.squareup.moshi.CollectionJsonAdapter#FACTORY",
      // Class is not public
      "com.squareup.moshi.MapJsonAdapter#FACTORY",
      // Class is not public
      "com.squareup.moshi.ArrayJsonAdapter#FACTORY",
    )
  }

tasks.named("check").configure { dependsOn(japicmp) }


================================================
FILE: moshi/records-tests/build.gradle.kts
================================================
plugins { `java-library` }

java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } }

tasks.withType<JavaCompile>().configureEach {
  // Target 16 to ensure minimum compatibility
  options.release.set(16)
}

dependencies {
  testImplementation(project(":moshi"))
  testCompileOnly(libs.jsr305)
  testImplementation(libs.junit)
  testImplementation(libs.truth)
}


================================================
FILE: moshi/records-tests/src/test/java/com/squareup/moshi/records/RecordsTest.java
================================================
/*
 * Copyright (C) 2021 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi.records;

import static com.google.common.truth.Truth.assertThat;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.junit.Assert.fail;

import com.squareup.moshi.FromJson;
import com.squareup.moshi.Json;
import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.JsonQualifier;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import com.squareup.moshi.Types;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import okio.Buffer;
import org.junit.Test;

public final class RecordsTest {

  private final Moshi moshi = new Moshi.Builder().build();

  @Test
  public void smokeTest() throws IOException {
    var stringAdapter = moshi.adapter(String.class);
    var adapter =
        moshi
            .newBuilder()
            .add(CharSequence.class, stringAdapter)
            .add(Types.subtypeOf(CharSequence.class), stringAdapter)
            .add(Types.supertypeOf(CharSequence.class), stringAdapter)
            .build()
            .adapter(SmokeTestType.class);
    var instance =
        new SmokeTestType(
            "John",
            "Smith",
            25,
            List.of("American"),
            70.5f,
            null,
            true,
            List.of("super wildcards!"),
            List.of("extend wildcards!"),
            List.of("unbounded"),
            List.of("objectList"),
            new int[] {1, 2, 3},
            new String[] {"fav", "arrays"},
            Map.of("italian", "pasta"),
            Set.of(List.of(Map.of("someKey", new int[] {1}))),
            new Map[] {Map.of("Hello", "value")});
    var json = adapter.toJson(instance);
    var deserialized = adapter.fromJson(json);
    assertThat(deserialized).isEqualTo(instance);
  }

  public record SmokeTestType(
      @Json(name = "first_name") String firstName,
      @Json(name = "last_name") String lastName,
      int age,
      List<String> nationalities,
      float weight,
      Boolean tattoos, // Boxed primitive test
      boolean hasChildren,
      List<? super CharSequence> superWildcard,
      List<? extends CharSequence> extendsWildcard,
      List<?> unboundedWildcard,
      List<Object> objectList,
      int[] favoriteThreeNumbers,
      String[] favoriteArrayValues,
      Map<String, String> foodPreferences,
      Set<List<Map<String, int[]>>> setListMapArrayInt,
      Map<String, Object>[] nestedArray) {
    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      SmokeTestType that = (SmokeTestType) o;
      return age == that.age
          && Float.compare(that.weight, weight) == 0
          && hasChildren == that.hasChildren
          && firstName.equals(that.firstName)
          && lastName.equals(that.lastName)
          && nationalities.equals(that.nationalities)
          && Objects.equals(tattoos, that.tattoos)
          && superWildcard.equals(that.superWildcard)
          && extendsWildcard.equals(that.extendsWildcard)
          && unboundedWildcard.equals(that.unboundedWildcard)
          && objectList.equals(that.objectList)
          && Arrays.equals(favoriteThreeNumbers, that.favoriteThreeNumbers)
          && Arrays.equals(favoriteArrayValues, that.favoriteArrayValues)
          && foodPreferences.equals(that.foodPreferences)
          // && setListMapArrayInt.equals(that.setListMapArrayInt) // Nested array equality doesn't
          // carry over
          && Arrays.equals(nestedArray, that.nestedArray);
    }

    @Override
    public int hashCode() {
      int result =
          Objects.hash(
              firstName,
              lastName,
              age,
              nationalities,
              weight,
              tattoos,
              hasChildren,
              superWildcard,
              extendsWildcard,
              unboundedWildcard,
              objectList,
              foodPreferences,
              setListMapArrayInt);
      result = 31 * result + Arrays.hashCode(favoriteThreeNumbers);
      result = 31 * result + Arrays.hashCode(favoriteArrayValues);
      result = 31 * result + Arrays.hashCode(nestedArray);
      return result;
    }
  }

  @Test
  public void genericRecord() throws IOException {
    var adapter =
        moshi.<GenericRecord<String>>adapter(
            Types.newParameterizedTypeWithOwner(
                RecordsTest.class, GenericRecord.class, String.class));
    assertThat(adapter.fromJson("{\"value\":\"Okay!\"}")).isEqualTo(new GenericRecord<>("Okay!"));
  }

  public record GenericRecord<T>(T value) {}

  @Test
  public void genericBoundedRecord() throws IOException {
    var adapter =
        moshi.<GenericBoundedRecord<Integer>>adapter(
            Types.newParameterizedTypeWithOwner(
                RecordsTest.class, GenericBoundedRecord.class, Integer.class));
    assertThat(adapter.fromJson("{\"value\":4}")).isEqualTo(new GenericBoundedRecord<>(4));
  }

  @Test
  public void indirectGenerics() throws IOException {
    var value =
        new HasIndirectGenerics(
            new IndirectGenerics<>(1L, List.of(2L, 3L, 4L), Map.of("five", 5L)));
    var jsonAdapter = moshi.adapter(HasIndirectGenerics.class);
    var json = "{\"value\":{\"single\":1,\"list\":[2,3,4],\"map\":{\"five\":5}}}";
    assertThat(jsonAdapter.toJson(value)).isEqualTo(json);
    assertThat(jsonAdapter.fromJson(json)).isEqualTo(value);
  }

  public record IndirectGenerics<T>(T single, List<T> list, Map<String, T> map) {}

  public record HasIndirectGenerics(IndirectGenerics<Long> value) {}

  @Test
  public void qualifiedValues() throws IOException {
    var adapter = moshi.newBuilder().add(new ColorAdapter()).build().adapter(QualifiedValues.class);
    assertThat(adapter.fromJson("{\"value\":\"#ff0000\"}"))
        .isEqualTo(new QualifiedValues(16711680));
  }

  public record QualifiedValues(@HexColor int value) {}

  @Retention(RUNTIME)
  @JsonQualifier
  @interface HexColor {}

  /** Converts strings like #ff0000 to the corresponding color ints. */
  public static class ColorAdapter {
    @ToJson
    public String toJson(@HexColor int rgb) {
      return String.format("#%06x", rgb);
    }

    @FromJson
    @HexColor
    public int fromJson(String rgb) {
      return Integer.parseInt(rgb.substring(1), 16);
    }
  }

  public record GenericBoundedRecord<T extends Number>(T value) {}

  @Test
  public void jsonName() throws IOException {
    var adapter = moshi.adapter(JsonName.class);
    assertThat(adapter.fromJson("{\"actualValue\":3}")).isEqualTo(new JsonName(3));
  }

  public record JsonName(@Json(name = "actualValue") int value) {}

  /**
   * We had a bug where we were incorrectly wrapping exceptions thrown when delegating to the
   * JsonAdapters of component fields.
   */
  @Test
  public void memberEncodeDecodeThrowsExceptionException() throws IOException {
    var throwingAdapter =
        new Object() {
          @ToJson
          void booleanToJson(JsonWriter writer, boolean value) throws IOException {
            throw new IOException("boom!");
          }

          @FromJson
          boolean booleanFromJson(JsonReader reader) throws IOException {
            throw new IOException("boom!");
          }
        };
    var json = "{\"value\":true}";
    Moshi throwingMoshi = this.moshi.newBuilder().add(throwingAdapter).build();
    var adapter = throwingMoshi.adapter(BooleanRecord.class);
    try {
      adapter.fromJson(json);
      fail();
    } catch (IOException expected) {
      assertThat(expected).hasMessageThat().isEqualTo("boom!");
    }
    try {
      adapter.toJson(new Buffer(), new BooleanRecord(true));
      fail();
    } catch (IOException expected) {
      assertThat(expected).hasMessageThat().isEqualTo("boom!");
    }
  }

  public record BooleanRecord(boolean value) {}

  @Test
  public void absentPrimitiveFails() throws IOException {
    var adapter = moshi.adapter(AbsentValues.class);
    try {
      adapter.fromJson("{\"s\":\"\"}");
      fail();
    } catch (JsonDataException expected) {
      assertThat(expected).hasMessageThat().isEqualTo("Required value 'i' missing at $");
    }
  }

  @Test
  public void nullPrimitiveFails() throws IOException {
    var adapter = moshi.adapter(AbsentValues.class);
    try {
      adapter.fromJson("{\"s\":\"\",\"i\":null}");
      fail();
    } catch (JsonDataException expected) {
      assertThat(expected).hasMessageThat().isEqualTo("Expected an int but was NULL at path $.i");
    }
  }

  @Test
  public void absentObjectIsNull() throws IOException {
    var adapter = moshi.adapter(AbsentValues.class);
    String json = "{\"i\":5}";
    AbsentValues value = new AbsentValues(null, 5);
    assertThat(adapter.fromJson(json)).isEqualTo(value);
    assertThat(adapter.toJson(value)).isEqualTo(json);
  }

  @Test
  public void nullObjectIsNull() throws IOException {
    var adapter = moshi.adapter(AbsentValues.class);
    String json = "{\"i\":5,\"s\":null}";
    AbsentValues value = new AbsentValues(null, 5);
    assertThat(adapter.fromJson(json)).isEqualTo(value);
    assertThat(adapter.toJson(value)).isEqualTo("{\"i\":5}");
  }

  public record AbsentValues(String s, int i) {}
}


================================================
FILE: moshi/src/main/java/com/squareup/moshi/-JsonUtf8Reader.kt
================================================
/*
 * Copyright (C) 2010 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.moshi

import com.squareup.moshi.internal.JsonScope
import com.squareup.moshi.internal.JsonValueSource
import com.squareup.moshi.internal.knownNotNull
import java.math.BigDecimal
import okio.Buffer
import okio.BufferedSource
import okio.ByteString
import okio.ByteString.Companion.encodeUtf8
import okio.EOFException
import okio.IOException
import okio.buffer

@Suppress("ktlint:standard:class-naming") // Hide this symbol from Java callers.
internal class `-JsonUtf8Reader` : JsonReader {
  /** The input JSON. */
  private val source: BufferedSource
  private val buffer: Buffer
  private var peeked = PEEKED_NONE

  /**
   * A peeked value that was composed entirely of digits with an optional leading dash. Positive
   * values may not have a leading 0.
   */
  private var peekedLong = 0L

  /** The number of characters in a peeked number literal. */
  private var peekedNumberLength = 0

  /**
   * A peeked string that should be parsed on the next double, long or string. This is populated
   * before a numeric value is parsed and used if that parsing fails.
   */
  private var peekedString: String? = null

  /**
   * If non-null, the most recent value read was [nextSource]. The caller may be mid-stream so it is
   * necessary to call [JsonValueSource.discard] to get to the end of the current JSON value before
   * proceeding.
   */
  private var valueSource: JsonValueSource? = null

  constructor(source: BufferedSource) {
    this.source = source
    buffer = source.buffer
    pushScope(JsonScope.EMPTY_DOCUMENT)
  }

  /** Copy-constructor makes a deep copy for peeking. */
  constructor(copyFrom: `-JsonUtf8Reader`) : super(copyFrom) {
    val sourcePeek = copyFrom.source.peek()
    source = sourcePeek
    buffer = sourcePeek.buffer
    peeked = copyFrom.peeked
    peekedLong = copyFrom.peekedLong
    peekedNumberLength = copyFrom.peekedNumberLength
    peekedString = copyFrom.peekedString

    // Make sure our buffer has as many bytes as the source's buffer. This is necessary because
    // JsonUtf8Reader assumes any data it has peeked (like the peekedNumberLength) are buffered.
    sourcePeek.require(copyFrom.buffer.size)
  }

  override fun beginArray() {
    val p = peekIfNone()
    if (p == PEEKED_BEGIN_ARRAY) {
      pushScope(JsonScope.EMPTY_ARRAY)
      pathIndices[stackSize - 1] = 0
      peeked = PEEKED_NONE
    } else {
      throw JsonDataException("Expected BEGIN_ARRAY but was ${peek()} at path $path")
    }
  }

  override fun endArray() {
    val p = peekIfNone()
    if (p == PEEKED_END_ARRAY) {
      stackSize--
      pathIndices[stackSize - 1]++
      peeked = PEEKED_NONE
    } else {
      throw JsonDataException("Expected END_ARRAY but was ${peek()} at path $path")
    }
  }

  override fun beginObject() {
    val p = peekIfNone()
    if (p == PEEKED_BEGIN_OBJECT) {
      pushScope(JsonScope.EMPTY_OBJECT)
      peeked = PEEKED_NONE
    } else {
      throw JsonDataException("Expected BEGIN_OBJECT but was ${peek()} at path $path")
    }
  }

  override fun endObject() {
    val p = peekIfNone()
    if (p == PEEKED_END_OBJECT) {
      stackSize--
      pathNames[stackSize] = null // Free the last path name so that it can be garbage collected!
      pathIndices[stackSize - 1]++
      peeked = PEEKED_NONE
    } else {
      throw JsonDataException("Expected END_OBJECT but was ${peek()} at path $path")
    }
  }

  override fun hasNext(): Boolean {
    val p = peekIfNone()
    return p != PEEKED_END_OBJECT && p != PEEKED_END_ARRAY && p != PEEKED_EOF
  }

  override fun peek(): Token {
    return when (peekIfNone()) {
      PEEKED_BEGIN_OBJECT -> Token.BEGIN_OBJECT

      PEEKED_END_OBJECT -> Token.END_OBJECT

      PEEKED_BEGIN_ARRAY -> Token.BEGIN_ARRAY

      PEEKED_END_ARRAY -> Token.END_ARRAY

      PEEKED_SINGLE_QUOTED_NAME,
      PEEKED_DOUBLE_QUOTED_NAME,
      PEEKED_UNQUOTED_NAME,
      PEEKED_BUFFERED_NAME -> Token.NAME

      PEEKED_TRUE,
      PEEKED_FALSE -> Token.BOOLEAN

      PEEKED_NULL -> Token.NULL

      PEEKED_SINGLE_QUOTED,
      PEEKED_DOUBLE_QUOTED,
      PEEKED_UNQUOTED,
      PEEKED_BUFFERED -> Token.STRING

      PEEKED_LONG,
      PEEKED_NUMBER -> Token.NUMBER

      PEEKED_EOF -> Token.END_DOCUMENT

      else -> throw AssertionError()
    }
  }

  private fun doPeek(): Int {
    val peekStack = scopes[stackSize - 1]
    when (peekStack) {
      JsonScope.EMPTY_ARRAY -> scopes[stackSize - 1] = JsonScope.NONEMPTY_ARRAY

      JsonScope.NONEMPTY_ARRAY -> {
        // Look for a comma before the next element.
        val c = nextNonWhitespace(true).toChar()
        buffer.readByte() // consume ']' or ','.
        when (c) {
          ']' -> {
            return setPeeked(PEEKED_END_ARRAY)
          }

          ';' -> checkLenient()

          /*no op*/
          ',' -> Unit

          else -> throw syntaxError("Unterminated array")
        }
      }

      JsonScope.EMPTY_OBJECT,
      JsonScope.NONEMPTY_OBJECT -> {
        scopes[stackSize - 1] = JsonScope.DANGLING_NAME
        // Look for a comma before the next element.
        if (peekStack == JsonScope.NONEMPTY_OBJECT) {
          val c = nextNonWhitespace(true).toChar()
          buffer.readByte() // Consume '}' or ','.
          when (c) {
            '}' -> {
              return setPeeked(PEEKED_END_OBJECT)
            }

            /*no op*/
            ',' -> Unit

            ';' -> checkLenient()

            else -> throw syntaxError("Unterminated object")
          }
        }
        val next =
          when (val c = nextNonWhitespace(true).toChar()) {
            '"' -> {
              buffer.readByte() // consume the '\"'.
              PEEKED_DOUBLE_QUOTED_NAME
            }

            '\'' -> {
              buffer.readByte() // consume the '\''.
              checkLenient()
              PEEKED_SINGLE_QUOTED_NAME
            }

            '}' ->
              if (peekStack != JsonScope.NONEMPTY_OBJECT) {
                buffer.readByte() // consume the '}'.
                PEEKED_END_OBJECT
              } else {
                throw syntaxError("Expected name")
              }

            else -> {
              checkLenient()
              if (isLiteral(c.code)) {
                PEEKED_UNQUOTED_NAME
              } else {
                throw syntaxError("Expected name")
              }
            }
          }
        peeked = next
        return next
      }

      JsonScope.DANGLING_NAME -> {
        scopes[stackSize - 1] = JsonScope.NONEMPTY_OBJECT
        // Look for a colon before the value.
        val c = nextNonWhitespace(true).toChar()
        buffer.readByte() // Consume ':'.
        when (c) {
          /*no op*/
          ':' -> Unit

          '=' -> {
            checkLenient()
            if (source.request(1) && buffer[0].asChar() == '>') {
              buffer.readByte() // Consume '>'.
            }
          }

          else -> throw syntaxError("Expected ':'")
        }
      }

      JsonScope.EMPTY_DOCUMENT -> scopes[stackSize - 1] = JsonScope.NONEMPTY_DOCUMENT

      JsonScope.NONEMPTY_DOCUMENT -> {
        if (nextNonWhitespace(false) == -1) {
          return setPeeked(PEEKED_EOF)
        } else {
          checkLenient()
        }
      }

      JsonScope.STREAMING_VALUE -> {
        valueSource!!.discard()
        valueSource = null
        stackSize--
        return doPeek()
      }

      else -> check(peekStack != JsonScope.CLOSED) { "JsonReader is closed" }
    }

    when (nextNonWhitespace(true).toChar()) {
      ']' -> {
        return when (peekStack) {
          JsonScope.EMPTY_ARRAY -> {
            buffer.readByte() // Consume ']'.
            setPeeked(PEEKED_END_ARRAY)
          }

          JsonScope.NONEMPTY_ARRAY -> {
            // In lenient mode, a 0-length literal in an array means 'null'.
            checkLenient()
            setPeeked(PEEKED_NULL)
          }

          else -> throw syntaxError("Unexpected value")
        }
      }

      // In lenient mode, a 0-length literal in an array means 'null'.
      ';',
      ',' ->
        return when (peekStack) {
          JsonScope.EMPTY_ARRAY,
          JsonScope.NONEMPTY_ARRAY -> {
            checkLenient()
            setPeeked(PEEKED_NULL)
          }

          else -> throw syntaxError("Unexpected value")
        }

      '\'' -> {
        checkLenient()
        buffer.readByte() // Consume '\''.
        return setPeeked(PEEKED_SINGLE_QUOTED)
      }

      '"' -> {
        buffer.readByte() // Consume '\"'.
        return setPeeked(PEEKED_DOUBLE_QUOTED)
      }

      '[' -> {
        buffer.readByte() // Consume '['.
        return setPeeked(PEEKED_BEGIN_ARRAY)
      }

      '{' -> {
        buffer.readByte() // Consume '{'.
        return setPeeked(PEEKED_BEGIN_OBJECT)
      }

      else -> Unit /* no-op */
    }
    var result = peekKeyword()
    if (result != PEEKED_NONE) {
      return result
    }
    result = peekNumber()
    if (result != PEEKED_NONE) {
      return result
    }
    if (!isLiteral(buffer[0].toInt())) {
      throw syntaxError("Expected value")
    }
    checkLenient()
    return setPeeked(PEEKED_UNQUOTED)
  }

  private fun peekKeyword(): Int {
    // Figure out which keyword we're matching against by its first character.
    var c = buffer[0].asChar()
    val keyword: String
    val keywordUpper: String
    val peeking: Int
    when (c) {
      't',
      'T' -> {
        keyword = "true"
        keywordUpper = "TRUE"
        peeking = PEEKED_TRUE
      }

      'f',
      'F' -> {
        keyword = "false"
        keywordUpper = "FALSE"
        peeking = PEEKED_FALSE
      }

      'n',
      'N' -> {
        keyword = "null"
        keywordUpper = "NULL"
        peeking = PEEKED_NULL
      }

      else -> return PEEKED_NONE
    }

    // Confirm that chars [1..length) match the keyword.
    val length = keyword.length
    for (i in 1 until length) {
      val iAsLong = i.toLong()
      if (!source.request(iAsLong + 1)) {
        return PEEKED_NONE
      }
      c = buffer[iAsLong].asChar()
      if (c != keyword[i] && c != keywordUpper[i]) {
        return PEEKED_NONE
      }
    }
    if (source.request((length + 1).toLong()) && isLiteral(buffer[length.toLong()].toInt())) {
      return PEEKED_NONE // Don't match trues, falsey or nullsoft!
    }

    // We've found the keyword followed either by EOF or by a non-literal character.
    buffer.skip(length.toLong())
    return setPeeked(peeking)
  }

  private fun peekNumber(): Int {
    var value = 0L // Negative to accommodate Long.MIN_VALUE more easily.
    var negative = false
    var fitsInLong = true
    var last = NUMBER_CHAR_NONE
    var i = 0L
    while (true) {
      if (!source.request(i + 1)) {
        break
      }
      when (val c = buffer[i].asChar()) {
        '-' -> {
          when (last) {
            NUMBER_CHAR_NONE -> {
              negative = true
              last = NUMBER_CHAR_SIGN
              i++
              continue
            }

            NUMBER_CHAR_EXP_E -> {
              last = NUMBER_CHAR_EXP_SIGN
              i++
              continue
            }
          }
          return PEEKED_NONE
        }

        '+' -> {
          if (last == NUMBER_CHAR_EXP_E) {
            last = NUMBER_CHAR_EXP_SIGN
            i++
            continue
          }
          return PEEKED_NONE
        }

        'e',
        'E' -> {
          if (last == NUMBER_CHAR_DIGIT || last == NUMBER_CHAR_FRACTION_DIGIT) {
            last = NUMBER_CHAR_EXP_E
            i++
            continue
          }
          return PEEKED_NONE
        }

        '.' -> {
          if (last == NUMBER_CHAR_DIGIT) {
            last = NUMBER_CHAR_DECIMAL
            i++
            continue
          }
          return PEEKED_NONE
        }

        else -> {
          if (c !in '0'..'9') {
            if (!isLiteral(c.code)) break
            return PEEKED_NONE
          }
          when (last) {
            NUMBER_CHAR_SIGN,
            NUMBER_CHAR_NONE -> {
              value = -(c - '0').toLong()
              last = NUMBER_CHAR_DIGIT
            }

            NUMBER_CHAR_DIGIT -> {
              if (value == 0L) {
                return PEEKED_NONE // Leading '0' prefix is not allowed (since it could be octal).
              }
              val newValue = value * 10 - (c - '0').toLong()
              fitsInLong =
                fitsInLong and
                  ((value > MIN_INCOMPLETE_INTEGER) ||
                    ((value == MIN_INCOMPLETE_INTEGER) && (newValue < value)))
              value = newValue
            }

            NUMBER_CHAR_DECIMAL -> last = NUMBER_CHAR_FRACTION_DIGIT

            NUMBER_CHAR_EXP_E,
            NUMBER_CHAR_EXP_SIGN -> last = NUMBER_CHAR_EXP_DIGIT
          }
        }
      }
      i++
    }

    // We've read a complete number. Decide if it's a PEEKED_LONG or a PEEKED_NUMBER.
    return when {
      last == NUMBER_CHAR_DIGIT &&
        fitsInLong &&
        (value != Long.MIN_VALUE || negative) &&
        (value != 0L || !negative) -> {
        peekedLong = if (negative) value else -value
        buffer.skip(i)
        setPeeked(PEEKED_LONG)
      }

      last == NUMBER_CHAR_DIGIT ||
        last == NUMBER_CHAR_FRACTION_DIGIT ||
        last == NUMBER_CHAR_EXP_DIGIT -> {
        peekedNumberLength = i.toInt()
        setPeeked(PEEKED_NUMBER)
      }

      else -> PEEKED_NONE
    }
  }

  @Throws(IOException::class)
  private fun isLiteral(c: Int): Boolean {
    return when (c.toChar()) {
      '/',
      '\\',
      ';',
      '#',
      '=' -> {
        checkLenient() // fall-through
        false
      }

      // 0x000C = \f
      '{',
      '}',
      '[',
      ']',
      ':',
      ',',
      ' ',
      '\t',
      '\u000C',
      '\r',
      '\n' -> false

      else -> true
    }
  }

  @Throws(IOException::class)
  override fun nextName(): String {
    val result =
      when (peekIfNone()) {
        PEEKED_UNQUOTED_NAME -> nextUnquotedValue()

        PEEKED_DOUBLE_QUOTED_NAME -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)

        PEEKED_SINGLE_QUOTED_NAME -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH)

        PEEKED_BUFFERED_NAME -> {
          val name = peekedString!!
          peekedString = null
          name
        }

        else -> throw JsonDataException("Expected a name but was ${peek()} at path $path")
      }
    peeked = PEEKED_NONE
    pathNames[stackSize - 1] = result
    return result
  }

  @Throws(IOException::class)
  override fun selectName(options: Options): Int {
    val p = peekIfNone()
    if (p < PEEKED_SINGLE_QUOTED_NAME || p > PEEKED_BUFFERED_NAME) {
      return -1
    }
    if (p == PEEKED_BUFFERED_NAME) {
      return findName(peekedString, options)
    }
    var result = source.select(options.doubleQuoteSuffix)
    if (result != -1) {
      peeked = PEEKED_NONE
      pathNames[stackSize - 1] = options.strings[result]
      return result
    }

    // The next name may be unnecessary escaped. Save the last recorded path name, so that we
    // can restore the peek state in case we fail to find a match.
    val lastPathName = pathNames[stackSize - 1]
    val nextName = nextName()
    result = findName(nextName, options)
    if (result == -1) {
      peeked = PEEKED_BUFFERED_NAME
      peekedString = nextName
      // We can't push the path further, make it seem like nothing happened.
      pathNames[stackSize - 1] = lastPathName
    }
    return result
  }

  @Throws(IOException::class)
  override fun skipName() {
    if (failOnUnknown) {
      // Capture the peeked value before nextName() since it will reset its value.
      val peeked = peek()
      nextName() // Move the path forward onto the offending name.
      throw JsonDataException("Cannot skip unexpected $peeked at $path")
    }
    val p = peekIfNone()
    when {
      p == PEEKED_UNQUOTED_NAME -> skipUnquotedValue()

      p == PEEKED_DOUBLE_QUOTED_NAME -> skipQuotedValue(DOUBLE_QUOTE_OR_SLASH)

      p == PEEKED_SINGLE_QUOTED_NAME -> skipQuotedValue(SINGLE_QUOTE_OR_SLASH)

      p != PEEKED_BUFFERED_NAME ->
        throw JsonDataException("Expected a name but was ${peek()} at path $path")
    }
    peeked = PEEKED_NONE
    pathNames[stackSize - 1] = "null"
  }

  /**
   * If `name` is in `options` this consumes it and returns its index. Otherwise this returns -1 and
   * no name is consumed.
   */
  private fun findName(name: String?, options: Options): Int {
    val i = options.strings.indexOfFirst { it == name }
    return if (i > -1) {
      peeked = PEEKED_NONE
      pathNames[stackSize - 1] = name
      i
    } else {
      -1
    }
  }

  override fun nextString(): String {
    val result =
      when (peekIfNone()) {
        PEEKED_UNQUOTED -> nextUnquotedValue()

        PEEKED_DOUBLE_QUOTED -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)

        PEEKED_SINGLE_QUOTED -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH)

        PEEKED_BUFFERED -> {
          val buffered = peekedString!!
          peekedString = null
          buffered
        }

        PEEKED_LONG -> peekedLong.toString()

        PEEKED_NUMBER -> buffer.readUtf8(peekedNumberLength.toLong())

        else -> throw JsonDataException("Expected a string but was ${peek()} at path $path")
      }
    peeked = PEEKED_NONE
    pathIndices[stackSize - 1]++
    return result
  }

  override fun selectString(options: Options): Int {
    val p = peekIfNone()
    if (p < PEEKED_SINGLE_QUOTED || p > PEEKED_BUFFERED) {
      return -1
    }
    if (p == PEEKED_BUFFERED) {
      return findString(peekedString, options)
    }
    var result = source.select(options.doubleQuoteSuffix)
    if (result != -1) {
      peeked = PEEKED_NONE
      pathIndices[stackSize - 1]++
      return result
    }
    val nextString = nextString()
    result = findString(nextString, options)
    if (result == -1) {
      peeked = PEEKED_BUFFERED
      peekedString = nextString
      pathIndices[stackSize - 1]--
    }
    return result
  }

  /**
   * If `string` is in `options` this consumes it and returns its index. Otherwise this returns -1
   * and no string is consumed.
   */
  private fun findString(string: String?, options: Options): Int {
    val i = options.strings.indexOfFirst { it == string }
    return if (i > -1) {
      peeked = PEEKED_NONE
      pathIndices[stackSize - 1]++
      i
    } else {
      -1
    }
  }

  override fun nextBoolean(): Boolean {
    return when (peekIfNone()) {
      PEEKED_TRUE -> {
        peeked = PEEKED_NONE
        pathIndices[stackSize - 1]++
        true
      }

      PEEKED_FALSE -> {
        peeked = PEEKED_NONE
        pathIndices[stackSize - 1]++
        false
      }

      else -> throw JsonDataException("Expected a boolean but was ${peek()} at path $path")
    }
  }

  override fun <T> nextNull(): T? {
    val p = peekIfNone()
    return if (p == PEEKED_NULL) {
      peeked = PEEKED_NONE
      pathIndices[stackSize - 1]++
      null
    } else {
      throw JsonDataException("Expected null but was ${peek()} at path $path")
    }
  }

  override fun nextDouble(): Double {
    val p = peekIfNone()
    if (p == PEEKED_LONG) {
      peeked = PEEKED_NONE
      pathIndices[stackSize - 1]++
      return peekedLong.toDouble()
    }
    val next =
      when (p) {
        PEEKED_NUMBER -> buffer.readUtf8(peekedNumberLength.toLong()).also { peekedString = it }

        PEEKED_DOUBLE_QUOTED -> nextQuotedValue(DOUBLE_QUOTE_OR_SLASH).also { peekedString = it }

        PEEKED_SINGLE_QUOTED -> nextQuotedValue(SINGLE_QUOTE_OR_SLASH).also { peekedString = it }

        PEEKED_UNQUOTED -> nextUnquotedValue().also { peekedString = it }

        PEEKED_BUFFERED -> {
          // PEEKED_BUFFERED means the value's been stored in peekedString
          knownNotNull(peekedString)
        }

        else -> throw JsonDataException("Expected a double but was " + peek() + " at path " + path)
      }
    peeked = PEEKED_BUFFERED
    val result =
      try {
        next.toDouble()
      } catch (_: NumberFormatException) {
        throw JsonDataException("Expected a double but was $next at path $path")
      }
    if (!lenient && (result.isNaN() || result.isInfinite())) {
      throw JsonEncodingException("JSON forbids NaN and infinities: $result at path $path")
    }
    peekedString = null
    peeked = PEEKED_NONE
    pathIndices[stackSize - 1]++
    return result
  }

  override fun nextLong(): Long {
    val p = peekIfNone()
    if (p == PEEKED_LONG) {
      peeked = PEEKED_NONE
      pathIndices[stackSize - 1]++
      return peekedLong
    }
    when {
      p == PEEKED_NUMBER -> peekedString = buffer.readUtf8(peekedNumberLength.toLong())

      p == PEEKED_DOUBLE_QUOTED || p == PEEKED_SINGLE_QUOTED -> {
        peekedString =
          if (p == PEEKED_DOUBLE_QUOTED) {
            nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
          } else {
            nextQuotedValue(SINGLE_QUOTE_OR_SLASH)
          }
        try {
          val result = peekedString!!.toLong()
          peeked = PEEKED_NONE
          pathIndices[stackSize - 1]++
          return result
        } catch (_: NumberFormatException) {
          // Fall back to parse as a BigDecimal below.
        }
      }

      p != PEEKED_BUFFERED -> {
        throw JsonDataException("Expected a long but was " + peek() + " at path " + path)
      }
    }
    peeked = PEEKED_BUFFERED
    val result =
      try {
        val asDecimal = BigDecimal(peekedString)
        asDecimal.longValueExact()
      } catch (_: NumberFormatException) {
        throw JsonDataException("Expected a long but was $peekedString at path $path")
      } catch (_: ArithmeticException) {
        throw JsonDataException("Expected a long but was $peekedString at path $path")
      }
    peekedString = null
    peeked = PEEKED_NONE
    pathIndices[stackSize - 1]++
    return result
  }

  /**
   * Returns the string up to but not including `quote`, unescaping any character escape sequences
   * encountered along the way. The opening quote should have already been read. This consumes the
   * closing quote, but does not include it in the returned string.
   *
   * @throws IOException if any Unicode escape sequences are malformed.
   */
  private fun nextQuotedValue(runTerminator: ByteString): String {
    var builder: StringBuilder? = null
    while (true) {
      val index = source.indexOfElement(runTerminator)
      if (index == -1L) throw syntaxError("Unterminated string")

      // If we've got an escape character, we're going to need a string builder.
      if (buffer[index].asChar() == '\\') {
        if (builder == null) builder = StringBuilder()
        builder.append(buffer.readUtf8(index))
        buffer.readByte() // '\'
        builder.append(readEscapeCharacter())
        continue
      }

      // If it isn't the escape character, it's the quote. Return the string.
      return if (builder == null) {
        buffer.readUtf8(index).also {
          buffer.readByte() // Consume the quote character.
        }
      } else {
        builder.append(buffer.readUtf8(index))
        buffer.readByte() // Consume the quote character.
        builder.toString()
      }
    }
  }

  /** Returns an unquoted value as a string. */
  private fun nextUnquotedValue(): String {
    val i = source.indexOfElement(UNQUOTED_STRING_TERMINALS)
    return if (i != -1L) buffer.readUtf8(i) else buffer.readUtf8()
  }

  private fun skipQuotedValue(runTerminator: ByteString) {
    while (true) {
      val index = source.indexOfElement(runTerminator)
      if (index == -1L) throw syntaxError("Unterminated string")
      val terminator = buffer[index].asChar()
      buffer.skip(index + 1)
      if (terminator == '\\') {
        readEscapeCharacter()
      } else {
        return
      }
    }
  }

  private fun skipUnquotedValue() {
    val i = source.indexOfElement(UNQUOTED_STRING_TERMINALS)
    buffer.skip(if (i != -1L) i else buffer.size)
  }

  override fun nextInt(): Int {
    val p = peekIfNone()
    if (p == PEEKED_LONG) {
      val result = peekedLong.toInt()
      if (peekedLong != result.toLong()) { // Make sure no precision was lost casting to 'int'.
        throw JsonDataException("Expected an int but was $peekedLong at path $path")
      }
      peeked = PEEKED_NONE
      pathIndices[stackSize - 1]++
      return result
    }
    val next: String =
      when (p) {
        PEEKED_NUMBER -> {
          buffer.readUtf8(peekedNumberLength.toLong()).also { peekedString = it }
        }

        PEEKED_DOUBLE_QUOTED,
        PEEKED_SINGLE_QUOTED -> {
          val next =
            if (p == PEEKED_DOUBLE_QUOTED) {
              nextQuotedValue(DOUBLE_QUOTE_OR_SLASH)
            } else {
              nextQuotedValue(SINGLE_QUOTE_OR_SLASH)
            }
          peekedString = next
          try {
            val result = next.toInt()
            peeked = PEEKED_NONE
            pathIndices[stackSize - 1]++
            return result
          } catch (_: NumberFormatException) {
            // Fall back to parse as a double below.
            next
          }
        }

        PEEKED_BUFFERED -> {
          // PEEKED_BUFFERED means the value's been stored in peekedString
          knownNotNull(peekedString)
        }

      
Download .txt
gitextract_wxuqnsxb/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── config.yml
│   │   └── feature_request.md
│   ├── renovate.json5
│   └── workflows/
│       ├── .java-version
│       ├── build.yml
│       └── release.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── build.gradle.kts
├── examples/
│   ├── build.gradle.kts
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── recipes/
│                               ├── ByteStrings.java
│                               ├── CardAdapter.java
│                               ├── CustomAdapterFactory.java
│                               ├── CustomAdapterWithDelegate.java
│                               ├── CustomFieldName.java
│                               ├── CustomQualifier.java
│                               ├── CustomTypeAdapter.java
│                               ├── DefaultOnDataMismatchAdapter.java
│                               ├── FallbackEnum.java
│                               ├── FromJsonWithoutStrings.java
│                               ├── IncludeNullsForAnnotatedTypes.java
│                               ├── IncludeNullsForOneType.java
│                               ├── JsonString.kt
│                               ├── MultipleFormats.java
│                               ├── ReadAndWriteRfc3339Dates.java
│                               ├── ReadJson.java
│                               ├── ReadJsonList.java
│                               ├── ReadJsonListKt.kt
│                               ├── RecoverFromTypeMismatch.java
│                               ├── Unwrap.java
│                               ├── WriteJson.java
│                               ├── models/
│                               │   ├── BlackjackHand.java
│                               │   ├── Card.java
│                               │   ├── Player.java
│                               │   ├── Suit.java
│                               │   └── Tournament.java
│                               └── package-info.java
├── gradle/
│   ├── libs.versions.toml
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── moshi/
│   ├── build.gradle.kts
│   ├── gradle.properties
│   ├── japicmp/
│   │   └── build.gradle.kts
│   ├── records-tests/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── test/
│   │           └── java/
│   │               └── com/
│   │                   └── squareup/
│   │                       └── moshi/
│   │                           └── records/
│   │                               └── RecordsTest.java
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── squareup/
│       │   │           └── moshi/
│       │   │               ├── -JsonUtf8Reader.kt
│       │   │               ├── -JsonUtf8Writer.kt
│       │   │               ├── -JsonValueReader.kt
│       │   │               ├── -JsonValueWriter.kt
│       │   │               ├── -MoshiKotlinExtensions.kt
│       │   │               ├── -MoshiKotlinTypesExtensions.kt
│       │   │               ├── FromJson.kt
│       │   │               ├── Json.kt
│       │   │               ├── JsonAdapter.kt
│       │   │               ├── JsonClass.kt
│       │   │               ├── JsonDataException.kt
│       │   │               ├── JsonEncodingException.kt
│       │   │               ├── JsonQualifier.kt
│       │   │               ├── JsonReader.kt
│       │   │               ├── JsonWriter.kt
│       │   │               ├── Moshi.kt
│       │   │               ├── ToJson.kt
│       │   │               ├── Types.kt
│       │   │               ├── internal/
│       │   │               │   ├── AdapterMethodsFactory.kt
│       │   │               │   ├── ArrayJsonAdapter.kt
│       │   │               │   ├── ClassFactory.kt
│       │   │               │   ├── ClassJsonAdapter.kt
│       │   │               │   ├── CollectionJsonAdapter.kt
│       │   │               │   ├── JsonScope.kt
│       │   │               │   ├── JsonValueSource.kt
│       │   │               │   ├── KotlinReflectTypes.kt
│       │   │               │   ├── LinkedHashTreeMap.kt
│       │   │               │   ├── MapJsonAdapter.kt
│       │   │               │   ├── NonNullJsonAdapter.kt
│       │   │               │   ├── NullSafeJsonAdapter.kt
│       │   │               │   ├── RecordJsonAdapter.kt
│       │   │               │   ├── StandardJsonAdapters.kt
│       │   │               │   └── Util.kt
│       │   │               └── package-info.java
│       │   ├── java16/
│       │   │   └── com/
│       │   │       └── squareup/
│       │   │           └── moshi/
│       │   │               └── internal/
│       │   │                   └── RecordJsonAdapter.kt
│       │   └── resources/
│       │       └── META-INF/
│       │           └── proguard/
│       │               └── moshi.pro
│       └── test/
│           └── java/
│               ├── android/
│               │   └── util/
│               │       └── Pair.java
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           ├── AdapterMethodsTest.java
│                           ├── CircularAdaptersTest.java
│                           ├── DeferredAdapterTest.java
│                           ├── FlattenTest.java
│                           ├── JsonAdapterTest.java
│                           ├── JsonCodecFactory.java
│                           ├── JsonQualifiersTest.java
│                           ├── JsonReaderPathTest.java
│                           ├── JsonReaderTest.java
│                           ├── JsonUtf8ReaderTest.java
│                           ├── JsonUtf8WriterTest.java
│                           ├── JsonValueReaderTest.java
│                           ├── JsonValueWriterTest.java
│                           ├── JsonWriterPathTest.java
│                           ├── JsonWriterTest.java
│                           ├── KotlinExtensionsTest.kt
│                           ├── MoshiTest.java
│                           ├── MoshiTesting.kt
│                           ├── ObjectAdapterTest.java
│                           ├── PromoteNameToValueTest.java
│                           ├── RecursiveTypesResolveTest.java
│                           ├── TestUtil.java
│                           ├── TypesTest.java
│                           └── internal/
│                               ├── ClassJsonAdapterTest.java
│                               ├── JsonValueSourceTest.java
│                               ├── KotlinReflectTypesTest.kt
│                               ├── LinkedHashTreeMapTest.java
│                               └── MapJsonAdapterTest.java
├── moshi-adapters/
│   ├── README.md
│   ├── build.gradle.kts
│   ├── japicmp/
│   │   └── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── squareup/
│       │               └── moshi/
│       │                   ├── Rfc3339DateJsonAdapter.kt
│       │                   └── adapters/
│       │                       ├── EnumJsonAdapter.kt
│       │                       ├── Iso8601Utils.kt
│       │                       ├── PolymorphicJsonAdapterFactory.kt
│       │                       └── Rfc3339DateJsonAdapter.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── adapters/
│                               ├── EnumJsonAdapterTest.java
│                               ├── PolymorphicJsonAdapterFactoryTest.java
│                               └── Rfc3339DateJsonAdapterTest.java
├── moshi-kotlin/
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── squareup/
│       │   │           └── moshi/
│       │   │               ├── KotlinJsonAdapterFactory.kt
│       │   │               └── kotlin/
│       │   │                   └── reflect/
│       │   │                       ├── IndexedParameterMap.kt
│       │   │                       ├── Invokable.kt
│       │   │                       ├── JvmDescriptors.kt
│       │   │                       ├── JvmSignatureSearcher.kt
│       │   │                       ├── KmExecutable.kt
│       │   │                       ├── KotlinJsonAdapterFactory.kt
│       │   │                       └── KtTypes.kt
│       │   └── resources/
│       │       └── META-INF/
│       │           └── com.android.tools/
│       │               ├── proguard/
│       │               │   └── moshi-metadata-reflect.pro
│       │               ├── r8-from-1.6.0/
│       │               │   └── moshi-metadata-reflect.pro
│       │               └── r8-upto-1.6.0/
│       │                   └── moshi-metadata-reflect.pro
│       └── test/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── kotlin/
│                               └── reflect/
│                                   └── KotlinJsonAdapterTest.kt
├── moshi-kotlin-codegen/
│   ├── build.gradle.kts
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── squareup/
│       │               └── moshi/
│       │                   └── kotlin/
│       │                       └── codegen/
│       │                           ├── api/
│       │                           │   ├── AdapterGenerator.kt
│       │                           │   ├── DelegateKey.kt
│       │                           │   ├── InternalMoshiCodegenApi.kt
│       │                           │   ├── Options.kt
│       │                           │   ├── ProguardRules.kt
│       │                           │   ├── PropertyGenerator.kt
│       │                           │   ├── TargetConstructor.kt
│       │                           │   ├── TargetParameter.kt
│       │                           │   ├── TargetProperty.kt
│       │                           │   ├── TargetType.kt
│       │                           │   ├── TypeRenderer.kt
│       │                           │   ├── kotlintypes.kt
│       │                           │   └── typeAliasUnwrapping.kt
│       │                           └── ksp/
│       │                               ├── AppliedType.kt
│       │                               ├── JsonClassSymbolProcessorProvider.kt
│       │                               ├── KspUtil.kt
│       │                               ├── MoshiApiUtil.kt
│       │                               ├── TargetTypes.kt
│       │                               └── shadedUtil.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── kotlin/
│                               └── codegen/
│                                   ├── JavaSuperclass.java
│                                   └── ksp/
│                                       └── JsonClassSymbolProcessorTest.kt
├── moshi-kotlin-tests/
│   ├── build.gradle.kts
│   ├── codegen-only/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── test/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── squareup/
│   │                       └── moshi/
│   │                           └── kotlin/
│   │                               └── codegen/
│   │                                   ├── CompileOnlyTests.kt
│   │                                   ├── ComplexGenericsInheritanceTest.kt
│   │                                   ├── DefaultConstructorTest.kt
│   │                                   ├── GeneratedAdaptersTest.kt
│   │                                   ├── GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter.kt
│   │                                   ├── LooksLikeAClass/
│   │                                   │   └── ClassInPackageThatLooksLikeAClass.kt
│   │                                   ├── MixingReflectAndCodeGen.kt
│   │                                   ├── MoshiKspTest.kt
│   │                                   ├── MultipleMasksTest.kt
│   │                                   └── annotation/
│   │                                       └── UppercaseInAnnotationPackage.kt
│   ├── extra-moshi-test-module/
│   │   ├── build.gradle.kts
│   │   └── src/
│   │       └── main/
│   │           └── kotlin/
│   │               └── com/
│   │                   └── squareup/
│   │                       └── moshi/
│   │                           └── kotlin/
│   │                               └── codegen/
│   │                                   └── test/
│   │                                       └── extra/
│   │                                           └── AbstractClassInModuleA.kt
│   └── src/
│       └── test/
│           └── kotlin/
│               └── com/
│                   └── squareup/
│                       └── moshi/
│                           └── kotlin/
│                               ├── DualKotlinTest.kt
│                               └── reflect/
│                                   └── KotlinJsonAdapterTest.kt
├── releasing.md
└── settings.gradle.kts
Download .txt
SYMBOL INDEX (1070 symbols across 55 files)

FILE: examples/src/main/java/com/squareup/moshi/recipes/ByteStrings.java
  class ByteStrings (line 25) | public final class ByteStrings {
    method run (line 26) | public void run() throws Exception {
    class Base64ByteStringAdapter (line 40) | public final class Base64ByteStringAdapter extends JsonAdapter<ByteStr...
      method fromJson (line 41) | @Override
      method toJson (line 47) | @Override
    method main (line 54) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/CardAdapter.java
  class CardAdapter (line 24) | public final class CardAdapter {
    method toJson (line 25) | @ToJson
    method fromJson (line 30) | @FromJson

FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomAdapterFactory.java
  class CustomAdapterFactory (line 32) | public final class CustomAdapterFactory {
    method run (line 33) | public void run() throws Exception {
    class SortedSetAdapter (line 53) | static final class SortedSetAdapter<T> extends JsonAdapter<SortedSet<T...
      method SortedSetAdapter (line 56) | SortedSetAdapter(JsonAdapter<T> elementAdapter) {
      method fromJson (line 60) | @Override
      method toJson (line 71) | @Override
    class SortedSetAdapterFactory (line 87) | static class SortedSetAdapterFactory implements JsonAdapter.Factory {
      method create (line 88) | @Override
    method main (line 111) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomAdapterWithDelegate.java
  class CustomAdapterWithDelegate (line 26) | public final class CustomAdapterWithDelegate {
    method run (line 27) | public void run() throws Exception {
    method main (line 38) | public static void main(String[] args) throws Exception {
    type Stage (line 42) | private enum Stage {
    class StageAdapter (line 53) | private static final class StageAdapter {
      method fromJson (line 54) | @FromJson

FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomFieldName.java
  class CustomFieldName (line 22) | public final class CustomFieldName {
    method run (line 23) | public void run() throws Exception {
    method main (line 33) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomQualifier.java
  class CustomQualifier (line 27) | public final class CustomQualifier {
    method run (line 28) | public void run() throws Exception {
    method main (line 44) | public static void main(String[] args) throws Exception {
    class Rectangle (line 48) | static class Rectangle {
      method toString (line 53) | @Override
    class ColorAdapter (line 63) | static class ColorAdapter {
      method toJson (line 64) | @ToJson
      method fromJson (line 69) | @FromJson

FILE: examples/src/main/java/com/squareup/moshi/recipes/CustomTypeAdapter.java
  class CustomTypeAdapter (line 22) | public final class CustomTypeAdapter {
    method run (line 23) | public void run() throws Exception {
    method main (line 41) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/DefaultOnDataMismatchAdapter.java
  class DefaultOnDataMismatchAdapter (line 29) | public final class DefaultOnDataMismatchAdapter<T> extends JsonAdapter<T> {
    method DefaultOnDataMismatchAdapter (line 33) | private DefaultOnDataMismatchAdapter(JsonAdapter<T> delegate, T defaul...
    method fromJson (line 38) | @Override
    method toJson (line 56) | @Override
    method newFactory (line 61) | public static <T> Factory newFactory(final Class<T> type, final T defa...

FILE: examples/src/main/java/com/squareup/moshi/recipes/FallbackEnum.java
  class FallbackEnum (line 34) | final class FallbackEnum {
    class FallbackEnumJsonAdapter (line 42) | public static final class FallbackEnumJsonAdapter<T extends Enum<T>> e...
      method create (line 45) | @Nullable
      method FallbackEnumJsonAdapter (line 73) | FallbackEnumJsonAdapter(Class<T> enumType, String fallbackName) {
      method fromJson (line 89) | @Override
      method toJson (line 97) | @Override
      method toString (line 102) | @Override
    class Example (line 108) | static final class Example {
      type Transportation (line 109) | enum Transportation {
      method Example (line 119) | Example(Transportation transportation) {
      method toString (line 123) | @Override
    method main (line 129) | public static void main(String[] args) throws Exception {
    method FallbackEnum (line 135) | private FallbackEnum() {}

FILE: examples/src/main/java/com/squareup/moshi/recipes/FromJsonWithoutStrings.java
  class FromJsonWithoutStrings (line 23) | public final class FromJsonWithoutStrings {
    method run (line 24) | public void run() throws Exception {
    method main (line 44) | public static void main(String[] args) throws Exception {
    class EventJson (line 48) | private static final class EventJson {
    class Event (line 54) | public static final class Event {
      method toString (line 58) | @Override
    class EventJsonAdapter (line 71) | private static final class EventJsonAdapter {
      method eventFromJson (line 72) | @FromJson
      method eventToJson (line 80) | @ToJson

FILE: examples/src/main/java/com/squareup/moshi/recipes/IncludeNullsForAnnotatedTypes.java
  class IncludeNullsForAnnotatedTypes (line 30) | public final class IncludeNullsForAnnotatedTypes {
    method run (line 31) | public void run() throws Exception {
    class Car (line 53) | @AlwaysSerializeNulls
    class Driver (line 60) | static class Driver {
    class AlwaysSerializeNullsFactory (line 66) | static class AlwaysSerializeNullsFactory implements JsonAdapter.Factory {
      method create (line 67) | @Override
    method main (line 78) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/IncludeNullsForOneType.java
  class IncludeNullsForOneType (line 27) | public final class IncludeNullsForOneType {
    method run (line 28) | public void run() throws Exception {
    class TournamentWithNullsAdapter (line 42) | public static final class TournamentWithNullsAdapter {
      method toJson (line 43) | @ToJson
    method main (line 57) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/MultipleFormats.java
  class MultipleFormats (line 32) | public final class MultipleFormats {
    method run (line 33) | public void run() throws Exception {
    class MultipleFormatsCardAdapter (line 51) | public final class MultipleFormatsCardAdapter {
      method toJson (line 52) | @ToJson
      method fromJson (line 58) | @FromJson
    class CardStringAdapter (line 73) | public final class CardStringAdapter {
      method toJson (line 74) | @ToJson
      method fromJson (line 79) | @FromJson
    method main (line 104) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/ReadAndWriteRfc3339Dates.java
  class ReadAndWriteRfc3339Dates (line 28) | public final class ReadAndWriteRfc3339Dates {
    method run (line 29) | public void run() throws Exception {
    method main (line 49) | public static void main(String[] args) throws Exception {
    method newDate (line 53) | private Date newDate(int year, int month, int day, int hour, int offse...

FILE: examples/src/main/java/com/squareup/moshi/recipes/ReadJson.java
  class ReadJson (line 22) | public final class ReadJson {
    method run (line 23) | public void run() throws Exception {
    method main (line 50) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/ReadJsonList.java
  class ReadJsonList (line 25) | public final class ReadJsonList {
    method run (line 26) | public void run() throws Exception {
    method main (line 53) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/RecoverFromTypeMismatch.java
  class RecoverFromTypeMismatch (line 24) | public final class RecoverFromTypeMismatch {
    method run (line 25) | public void run() throws Exception {
    method main (line 39) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/Unwrap.java
  class Unwrap (line 35) | final class Unwrap {
    method Unwrap (line 36) | private Unwrap() {}
    method main (line 38) | public static void main(String[] args) throws Exception {
    class EnvelopeJsonAdapter (line 53) | public static final class EnvelopeJsonAdapter extends JsonAdapter<Obje...
      method create (line 56) | @Override
      class Envelope (line 77) | private static final class Envelope<T> {
        method Envelope (line 80) | Envelope(T data) {
      method EnvelopeJsonAdapter (line 87) | EnvelopeJsonAdapter(JsonAdapter<Envelope<?>> delegate) {
      method fromJson (line 91) | @Override
      method toJson (line 96) | @Override

FILE: examples/src/main/java/com/squareup/moshi/recipes/WriteJson.java
  class WriteJson (line 28) | public final class WriteJson {
    method run (line 29) | public void run() throws Exception {
    method main (line 41) | public static void main(String[] args) throws Exception {

FILE: examples/src/main/java/com/squareup/moshi/recipes/models/BlackjackHand.java
  class BlackjackHand (line 20) | public final class BlackjackHand {
    method BlackjackHand (line 24) | public BlackjackHand(Card hiddenCard, List<Card> visibleCards) {
    method toString (line 29) | @Override

FILE: examples/src/main/java/com/squareup/moshi/recipes/models/Card.java
  class Card (line 18) | public final class Card {
    method Card (line 22) | public Card(char rank, Suit suit) {
    method toString (line 27) | @Override

FILE: examples/src/main/java/com/squareup/moshi/recipes/models/Player.java
  class Player (line 20) | public final class Player {
    method Player (line 24) | public Player(String username, int luckyNumber) {
    method toString (line 29) | @Override

FILE: examples/src/main/java/com/squareup/moshi/recipes/models/Suit.java
  type Suit (line 18) | public enum Suit {
    method toString (line 24) | @Override

FILE: examples/src/main/java/com/squareup/moshi/recipes/models/Tournament.java
  class Tournament (line 20) | public final class Tournament {
    method Tournament (line 25) | public Tournament(String name, String location, Date start) {
    method toString (line 31) | @Override

FILE: moshi-adapters/src/test/java/com/squareup/moshi/adapters/EnumJsonAdapterTest.java
  class EnumJsonAdapterTest (line 27) | @SuppressWarnings("CheckReturnValue")
    method toAndFromJson (line 29) | @Test
    method withJsonName (line 36) | @Test
    method withoutFallbackValue (line 43) | @Test
    method withFallbackValue (line 58) | @Test
    method withNullFallbackValue (line 67) | @Test
    type Roshambo (line 76) | enum Roshambo {

FILE: moshi-adapters/src/test/java/com/squareup/moshi/adapters/PolymorphicJsonAdapterFactoryTest.java
  class PolymorphicJsonAdapterFactoryTest (line 33) | @SuppressWarnings("CheckReturnValue")
    method fromJson (line 35) | @Test
    method toJson (line 52) | @Test
    method unregisteredLabelValue (line 69) | @Test
    method specifiedFallbackSubtype (line 95) | @Test
    method specifiedNullFallbackSubtype (line 112) | @Test
    method specifiedFallbackJsonAdapter (line 128) | @Test
    method unregisteredSubtype (line 165) | @Test
    method unregisteredSubtypeWithDefaultValue (line 191) | @Test
    method unregisteredSubtypeWithFallbackJsonAdapter (line 219) | @Test
    method nonStringLabelValue (line 247) | @Test
    method nonObjectDoesNotConsume (line 268) | @Test
    method nonUniqueSubtypes (line 292) | @Test
    method uniqueLabels (line 315) | @Test
    method nullSafe (line 327) | @Test
    method unportableTypes (line 347) | @Test
    method failOnUnknownMissingTypeLabel (line 365) | @Test
    method missingLabelKey (line 380) | @Test
    method missingLabelKeyWithSpecifiedFallbackJsonAdapter (line 401) | @Test
    method missingLabelKeyWithSpecifiedDefaultValue (line 435) | @Test
    type Message (line 452) | interface Message {}
    class Success (line 454) | static final class Success implements Message {
      method Success (line 457) | Success(String value) {
      method equals (line 461) | @Override
      method hashCode (line 469) | @Override
    class Error (line 475) | static final class Error implements Message {
      method Error (line 478) | Error(Map<String, Object> error_logs) {
      method equals (line 482) | @Override
      method hashCode (line 490) | @Override
    class EmptyMessage (line 496) | static final class EmptyMessage implements Message {
      method toString (line 497) | @Override
    class MessageWithUnportableTypes (line 503) | static final class MessageWithUnportableTypes implements Message {
      method MessageWithUnportableTypes (line 506) | MessageWithUnportableTypes(long long_value) {
    class MessageWithType (line 511) | static final class MessageWithType implements Message {
      method MessageWithType (line 515) | MessageWithType(String type, String value) {

FILE: moshi-adapters/src/test/java/com/squareup/moshi/adapters/Rfc3339DateJsonAdapterTest.java
  class Rfc3339DateJsonAdapterTest (line 30) | public final class Rfc3339DateJsonAdapterTest {
    method fromJsonWithTwoDigitMillis (line 33) | @Test
    method fromJson (line 39) | @Test
    method toJson (line 55) | @Test
    method nullSafety (line 71) | @Test
    method presentOrAbsentTime (line 77) | @Test
    method variableFractionDigits (line 86) | @Test
    method absentTimeZone (line 96) | @Test
    method newDate (line 107) | private Date newDate(
    method newDateWithHostZone (line 119) | private Date newDateWithHostZone(int year, int month, int day) {

FILE: moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/JavaSuperclass.java
  class JavaSuperclass (line 21) | public class JavaSuperclass {

FILE: moshi/records-tests/src/test/java/com/squareup/moshi/records/RecordsTest.java
  class RecordsTest (line 41) | public final class RecordsTest {
    method smokeTest (line 45) | @Test
    method equals (line 96) | @Override
    method hashCode (line 120) | @Override
    method genericRecord (line 144) | @Test
    method genericBoundedRecord (line 155) | @Test
    method indirectGenerics (line 164) | @Test
    method qualifiedValues (line 179) | @Test
    class ColorAdapter (line 193) | public static class ColorAdapter {
      method toJson (line 194) | @ToJson
      method fromJson (line 199) | @FromJson
    method jsonName (line 208) | @Test
    method memberEncodeDecodeThrowsExceptionException (line 220) | @Test
    method absentPrimitiveFails (line 253) | @Test
    method nullPrimitiveFails (line 264) | @Test
    method absentObjectIsNull (line 275) | @Test
    method nullObjectIsNull (line 284) | @Test

FILE: moshi/src/test/java/android/util/Pair.java
  class Pair (line 18) | public final class Pair {}

FILE: moshi/src/test/java/com/squareup/moshi/AdapterMethodsTest.java
  class AdapterMethodsTest (line 39) | public final class AdapterMethodsTest {
    method toAndFromJsonViaListOfIntegers (line 40) | @Test
    class PointAsListOfIntegersJsonAdapter (line 48) | static class PointAsListOfIntegersJsonAdapter {
      method pointToJson (line 49) | @ToJson
      method pointFromJson (line 54) | @FromJson
    method toAndFromJsonWithWriterAndReader (line 61) | @Test
    class PointWriterAndReaderJsonAdapter (line 69) | static class PointWriterAndReaderJsonAdapter {
      method pointToJson (line 70) | @ToJson
      method pointFromJson (line 78) | @FromJson
    class PointJsonAdapterWithDelegate (line 88) | private static final class PointJsonAdapterWithDelegate {
      method fromJson (line 89) | @FromJson
      method toJson (line 97) | @ToJson
    class PointJsonAdapterWithDelegateWithQualifier (line 105) | private static final class PointJsonAdapterWithDelegateWithQualifier {
      method fromJson (line 106) | @FromJson
      method toJson (line 115) | @ToJson
    method toAndFromWithDelegate (line 124) | @Test
    method toAndFromWithDelegateWithQualifier (line 133) | @Test
    method toAndFromWithIntermediate (line 146) | @Test
    method toAndFromWithIntermediateWithQualifier (line 168) | @Test
    method toJsonOnly (line 193) | @Test
    class PointAsListOfIntegersToAdapter (line 201) | static class PointAsListOfIntegersToAdapter {
      method pointToJson (line 202) | @ToJson
    method fromJsonOnly (line 208) | @Test
    class PointAsListOfIntegersFromAdapter (line 216) | static class PointAsListOfIntegersFromAdapter {
      method pointFromJson (line 217) | @FromJson
    method multipleLayersOfAdapters (line 224) | @Test
    class MultipleLayersJsonAdapter (line 232) | static class MultipleLayersJsonAdapter {
      method pointToJson (line 233) | @ToJson
      method integerListToJson (line 238) | @ToJson
      method pointFromJson (line 248) | @FromJson
      method listOfIntegersFromJson (line 254) | @FromJson
    method conflictingToAdapters (line 264) | @Test
    class ConflictingsToJsonAdapter (line 277) | static class ConflictingsToJsonAdapter {
      method pointToJson1 (line 278) | @ToJson
      method pointToJson2 (line 283) | @ToJson
    method conflictingFromAdapters (line 289) | @Test
    class ConflictingsFromJsonAdapter (line 302) | static class ConflictingsFromJsonAdapter {
      method pointFromJson1 (line 303) | @FromJson
      method pointFromJson2 (line 308) | @FromJson
    method emptyAdapters (line 314) | @Test
    class EmptyJsonAdapter (line 329) | static class EmptyJsonAdapter {}
    method unexpectedSignatureToAdapters (line 331) | @Test
    class UnexpectedSignatureToJsonAdapter (line 352) | static class UnexpectedSignatureToJsonAdapter {
      method pointToJson (line 353) | @ToJson
    method unexpectedSignatureFromAdapters (line 357) | @Test
    class UnexpectedSignatureFromJsonAdapter (line 378) | static class UnexpectedSignatureFromJsonAdapter {
      method pointFromJson (line 379) | @FromJson
    method toAndFromNullNotNullable (line 387) | @Test
    class NotNullablePointAsListOfIntegersJsonAdapter (line 396) | static class NotNullablePointAsListOfIntegersJsonAdapter {
      method pointToJson (line 397) | @ToJson
      method pointFromJson (line 402) | @FromJson
    method toAndFromNullNullable (line 408) | @Test
    class NullablePointAsListOfIntegersJsonAdapter (line 416) | static class NullablePointAsListOfIntegersJsonAdapter {
      method pointToJson (line 417) | @ToJson
      method pointFromJson (line 422) | @FromJson
    method toAndFromNullJsonWithWriterAndReader (line 433) | @Test
    class NullableIntToJsonAdapter (line 441) | static class NullableIntToJsonAdapter {
      method jsonToInt (line 442) | @FromJson
      method intToJson (line 451) | @ToJson
    method adapterThrows (line 461) | @Test
    class ExceptionThrowingPointJsonAdapter (line 480) | static class ExceptionThrowingPointJsonAdapter {
      method pointToJson (line 481) | @ToJson
      method pointFromJson (line 487) | @FromJson
    method adapterDoesToJsonOnly (line 494) | @Test
    method adapterDoesFromJsonOnly (line 523) | @Test
    method parameterizedTypeEqualsNotUsed (line 556) | @Test
    class ListOfStringJsonAdapter (line 568) | static class ListOfStringJsonAdapter {
      method listOfStringToJson (line 569) | @ToJson
      method listOfStringFromJson (line 579) | @FromJson
    method parameterizedTypeCacheKey (line 589) | @Test
    method writerAndReaderTakingJsonAdapterParameter (line 601) | @Test
    class JsonAdapterWithWriterAndReaderTakingJsonAdapterParameter (line 614) | static class JsonAdapterWithWriterAndReaderTakingJsonAdapterParameter {
      method lineToJson (line 615) | @ToJson
      method lineFromJson (line 624) | @FromJson
    method writerAndReaderTakingAnnotatedJsonAdapterParameter (line 634) | @Test
    class PointWithParensJsonAdapter (line 647) | static class PointWithParensJsonAdapter {
      method pointToJson (line 648) | @ToJson
      method pointFromJson (line 653) | @FromJson
    class JsonAdapterWithWriterAndReaderTakingAnnotatedJsonAdapterParameter (line 662) | static class JsonAdapterWithWriterAndReaderTakingAnnotatedJsonAdapterP...
      method lineToJson (line 663) | @ToJson
      method lineFromJson (line 672) | @FromJson
    method writerAndReaderTakingMultipleJsonAdapterParameters (line 683) | @Test
    class JsonAdapterWithWriterAndReaderTakingMultipleJsonAdapterParameters (line 697) | static class JsonAdapterWithWriterAndReaderTakingMultipleJsonAdapterPa...
      method lineToJson (line 698) | @ToJson
      method lineFromJson (line 711) | @FromJson
    method noToJsonAdapterTakingJsonAdapterParameter (line 727) | @Test
    class ToJsonAdapterTakingJsonAdapterParameter (line 737) | static class ToJsonAdapterTakingJsonAdapterParameter {
      method lineToJson (line 738) | @ToJson
    method noFromJsonAdapterTakingJsonAdapterParameter (line 744) | @Test
    class FromJsonAdapterTakingJsonAdapterParameter (line 754) | static class FromJsonAdapterTakingJsonAdapterParameter {
      method lineFromJson (line 755) | @FromJson
    method adaptedTypeIsEnclosedParameterizedType (line 761) | @Test
    class EnclosedParameterizedTypeJsonAdapter (line 773) | static class EnclosedParameterizedTypeJsonAdapter {
      method boxFromJson (line 774) | @FromJson
      method boxToJson (line 779) | @ToJson
    class Box (line 785) | static class Box<T> {
      method Box (line 788) | public Box(T data) {
      method equals (line 792) | @Override
      method hashCode (line 797) | @Override
    method genericArrayTypes (line 803) | @Test
    class ByteArrayJsonAdapter (line 816) | static class ByteArrayJsonAdapter {
      method byteArrayToJson (line 817) | @ToJson
      method byteArrayFromJson (line 822) | @FromJson
    class MapOfByteArrays (line 828) | static class MapOfByteArrays {
      method MapOfByteArrays (line 831) | public MapOfByteArrays(Map<String, byte[]> map) {
      method equals (line 835) | @Override
      method hashCode (line 840) | @Override
      method toString (line 845) | @Override
    class Point (line 856) | static class Point {
      method Point (line 860) | public Point(int x, int y) {
      method equals (line 865) | @Override
      method hashCode (line 870) | @Override
    class Line (line 876) | static class Line {
      method Line (line 880) | public Line(Point a, Point b) {
      method equals (line 885) | @Override
      method hashCode (line 890) | @Override
    type Shape (line 896) | interface Shape {
      method draw (line 897) | String draw();
    method brokenParameterizedType (line 905) | ParameterizedType brokenParameterizedType(

FILE: moshi/src/test/java/com/squareup/moshi/CircularAdaptersTest.java
  class CircularAdaptersTest (line 29) | public final class CircularAdaptersTest {
    class Team (line 30) | static class Team {
      method Team (line 34) | public Team(String lead, Project... projects) {
    class Project (line 40) | static class Project {
      method Project (line 44) | Project(String name, Team... teams) {
    method circularAdapters (line 50) | @Test
    class Node (line 82) | static class Node {
      method Node (line 87) | Node(String name, Node left, Node right) {
      method plusPrefix (line 93) | Node plusPrefix(String prefix) {
      method minusPrefix (line 97) | Node minusPrefix(String prefix) {
    class PrefixingNodeFactory (line 108) | static class PrefixingNodeFactory implements JsonAdapter.Factory {
      method create (line 109) | @Override
    method circularAdaptersAndAnnotations (line 139) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/DeferredAdapterTest.java
  class DeferredAdapterTest (line 32) | public final class DeferredAdapterTest {
    method concurrentSafe (line 45) | @Test
    method doInAnotherThread (line 84) | private void doInAnotherThread(Runnable runnable) {
    class BlueNode (line 97) | static class BlueNode {
      method BlueNode (line 101) | BlueNode(@Nullable GreenNode green, @Nullable RedNode red) {
    class RedNode (line 107) | static class RedNode {
      method RedNode (line 110) | RedNode(@Nullable BlueNode blue) {
    class GreenNode (line 115) | static class GreenNode {
      method GreenNode (line 118) | GreenNode(@Nullable BlueNode blue) {

FILE: moshi/src/test/java/com/squareup/moshi/FlattenTest.java
  class FlattenTest (line 31) | @RunWith(Parameterized.class)
    method parameters (line 35) | @Parameters(name = "{0}")
    method flattenExample (line 40) | @Test
    method flattenObject (line 58) | @Test
    method flattenArray (line 82) | @Test
    method recursiveFlatten (line 103) | @Test
    method flattenMultipleNested (line 134) | @Test
    method flattenIsOnlyOneLevelDeep (line 160) | @Test
    method flattenOnlySomeChildren (line 187) | @Test
    method multipleCallsToFlattenSameNesting (line 213) | @Test
    method deepFlatten (line 248) | @Test
    method flattenTopLevel (line 283) | @Test
    method flattenDoesNotImpactOtherTypesInObjects (line 294) | @Test
    method flattenDoesNotImpactOtherTypesInArrays (line 320) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java
  class JsonAdapterTest (line 35) | @RunWith(Parameterized.class)
    method parameters (line 39) | @Parameters(name = "{0}")
    method lenient (line 44) | @Test
    method nullSafe (line 75) | @Test
    method nonNull (line 106) | @Test
    method failOnUnknown (line 149) | @Test
    method indent (line 177) | @Test
    method indentDisallowsNull (line 204) | @Test
    method serializeNulls (line 226) | @Test
    method stringDocumentMustBeFullyConsumed (line 250) | @Test
    method adapterFromJsonStringPeeksAtEnd (line 272) | @Test
    method lenientAdapterFromJsonStringDoesNotPeekAtEnd (line 296) | @Test
    method adaptersDelegateLeniency (line 313) | @Test
    method nullSafeDoesntDuplicate (line 330) | @Test
    method nonNullDoesntDuplicate (line 336) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/JsonCodecFactory.java
  class JsonCodecFactory (line 26) | abstract class JsonCodecFactory {
    method factories (line 30) | static List<Object[]> factories() {
    method newReader (line 190) | abstract JsonReader newReader(String json) throws IOException;
    method newWriter (line 192) | abstract JsonWriter newWriter() throws IOException;
    method implementsStrictPrecision (line 194) | boolean implementsStrictPrecision() {
    method json (line 198) | abstract String json() throws IOException;
    method encodesToBytes (line 200) | boolean encodesToBytes() {
    method supportsBigNumbers (line 204) | boolean supportsBigNumbers() {

FILE: moshi/src/test/java/com/squareup/moshi/JsonQualifiersTest.java
  class JsonQualifiersTest (line 27) | public final class JsonQualifiersTest {
    method builtInTypes (line 28) | @Test
    class BuiltInTypesJsonAdapter (line 43) | static class BuiltInTypesJsonAdapter {
      method fooPrefixStringToString (line 44) | @ToJson
      method fooPrefixStringFromString (line 49) | @FromJson
    method readerWriterJsonAdapter (line 57) | @Test
    class ReaderWriterJsonAdapter (line 72) | static class ReaderWriterJsonAdapter {
      method fooPrefixStringToString (line 73) | @ToJson
      method fooPrefixStringFromString (line 78) | @FromJson
    class StringAndFooString (line 97) | static class StringAndFooString {
    class StringAndFooBazString (line 102) | static class StringAndFooBazString {
    method builtInTypesWithMultipleAnnotations (line 107) | @Test
    class BuiltInTypesWithMultipleAnnotationsJsonAdapter (line 123) | static class BuiltInTypesWithMultipleAnnotationsJsonAdapter {
      method fooPrefixAndBazSuffixStringToString (line 124) | @ToJson
      method fooPrefixAndBazSuffixStringFromString (line 129) | @FromJson
    method readerWriterWithMultipleAnnotations (line 139) | @Test
    class ReaderWriterWithMultipleAnnotationsJsonAdapter (line 155) | static class ReaderWriterWithMultipleAnnotationsJsonAdapter {
      method fooPrefixAndBazSuffixStringToString (line 156) | @ToJson
      method fooPrefixAndBazSuffixStringFromString (line 162) | @FromJson
    method basicTypesAnnotationDelegating (line 173) | @Test
    class BuiltInTypesDelegatingJsonAdapter (line 192) | static class BuiltInTypesDelegatingJsonAdapter {
      method fooPrefixAndBazSuffixStringToString (line 193) | @ToJson
      method fooPrefixAndBazSuffixStringFromString (line 199) | @FromJson
    method readerWriterAnnotationDelegating (line 208) | @Test
    method manualJsonAdapter (line 227) | @Test
    method noJsonAdapterForAnnotatedType (line 257) | @Test
    method annotationWithoutJsonQualifierIsIgnoredByAdapterMethods (line 267) | @Test
    class MissingJsonQualifierJsonAdapter (line 283) | static class MissingJsonQualifierJsonAdapter {
      method dateToJson (line 284) | @ToJson
      method jsonToDate (line 289) | @FromJson
    class DateAndMillisDate (line 300) | static class DateAndMillisDate {
    method annotationWithoutJsonQualifierIsRejectedOnRegistration (line 305) | @Test
    method annotationsConflict (line 332) | @Test
    class AnnotationsConflictJsonAdapter (line 342) | static class AnnotationsConflictJsonAdapter {
      method fooPrefixStringToString (line 343) | @ToJson
      method fooPrefixStringToString2 (line 348) | @ToJson
    method toButNoFromJson (line 354) | @Test
    class ToButNoFromJsonAdapter (line 385) | static class ToButNoFromJsonAdapter {
      method fooPrefixStringToString (line 386) | @ToJson
    method fromButNoToJson (line 392) | @Test
    class FromButNoToJsonAdapter (line 423) | static class FromButNoToJsonAdapter {
      method fooPrefixStringFromString (line 424) | @FromJson

FILE: moshi/src/test/java/com/squareup/moshi/JsonReaderPathTest.java
  class JsonReaderPathTest (line 29) | @RunWith(Parameterized.class)
    method parameters (line 33) | @Parameters(name = "{0}")
    method path (line 38) | @SuppressWarnings("CheckReturnValue")
    method arrayOfObjects (line 79) | @Test
    method arrayOfArrays (line 100) | @Test
    method objectPath (line 121) | @SuppressWarnings("CheckReturnValue")
    method arrayPath (line 163) | @SuppressWarnings("CheckReturnValue")
    method multipleTopLevelValuesInOneDocument (line 195) | @Test
    method skipArrayElements (line 209) | @Test
    method skipObjectNames (line 218) | @Test
    method skipObjectValues (line 226) | @SuppressWarnings("CheckReturnValue")
    method skipNestedStructures (line 238) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java
  class JsonReaderTest (line 41) | @RunWith(Parameterized.class)
    method parameters (line 46) | @Parameters(name = "{0}")
    method newReader (line 51) | JsonReader newReader(String json) throws IOException {
    method readArray (line 55) | @Test
    method readEmptyArray (line 65) | @Test
    method readObject (line 74) | @Test
    method readEmptyObject (line 86) | @Test
    method skipArray (line 95) | @Test
    method skipArrayAfterPeek (line 107) | @Test
    method skipTopLevelObject (line 120) | @Test
    method skipObject (line 127) | @Test
    method skipObjectAfterPeek (line 140) | @Test
    method skipInteger (line 162) | @Test
    method skipDouble (line 174) | @Test
    method failOnUnknownFailsOnUnknownObjectValue (line 186) | @Test
    method failOnUnknownFailsOnUnknownArrayElement (line 205) | @Test
    method helloWorld (line 224) | @Test
    method emptyString (line 239) | @Test
    method characterUnescaping (line 253) | @Test
    method integersWithFractionalPartSpecified (line 301) | @Test
    method doubles (line 310) | @Test
    method strictNonFiniteDoubles (line 337) | @Test
    method strictQuotedNonFiniteDoubles (line 349) | @Test
    method lenientNonFiniteDoubles (line 362) | @Test
    method lenientQuotedNonFiniteDoubles (line 374) | @Test
    method longs (line 386) | @Test
    method booleans (line 419) | @Test
    method nextFailuresDoNotAdvance (line 429) | @Test
    method integerMismatchWithDoubleDoesNotAdvance (line 490) | @Test
    method integerMismatchWithLongDoesNotAdvance (line 505) | @Test
    method longMismatchWithDoubleDoesNotAdvance (line 520) | @Test
    method stringNullIsNotNull (line 535) | @Test
    method nullLiteralIsNotAString (line 546) | @Test
    method topLevelValueTypes (line 557) | @Test
    method topLevelValueTypeWithSkipValue (line 584) | @Test
    method deeplyNestedArrays (line 591) | @Test
    method deeplyNestedObjects (line 607) | @Test
    method skipVeryLongUnquotedString (line 630) | @Test
    method skipTopLevelUnquotedString (line 639) | @Test
    method skipVeryLongQuotedString (line 647) | @Test
    method skipTopLevelQuotedString (line 655) | @Test
    method stringAsNumberWithTruncatedExponent (line 663) | @Test
    method stringAsNumberWithDigitAndNonDigitExponent (line 671) | @Test
    method stringAsNumberWithNonDigitExponent (line 679) | @Test
    method emptyStringName (line 687) | @Test
    method validEscapes (line 702) | @Test
    method selectName (line 709) | @Test
    method selectNameNecessaryEscaping (line 746) | @Test
    method selectNameUnnecessaryEscaping (line 765) | @Test
    method selectNameUnquoted (line 789) | @Test
    method selectNameSingleQuoted (line 805) | @Test
    method selectString (line 821) | @Test
    method selectStringNecessaryEscaping (line 849) | @Test
    method selectStringUnnecessaryEscaping (line 862) | @Test
    method selectStringUnquoted (line 874) | @Test
    method selectStringSingleQuoted (line 887) | @Test
    method selectStringMaintainsReaderState (line 900) | @Test
    method selectStringWithoutString (line 914) | @Test
    method stringToNumberCoersion (line 930) | @Test
    method unnecessaryPrecisionNumberCoersion (line 940) | @Test
    method nanInfinityDoubleCoersion (line 949) | @Test
    method intMismatchWithStringDoesNotAdvance (line 960) | @Test
    method longMismatchWithStringDoesNotAdvance (line 973) | @Test
    method doubleMismatchWithStringDoesNotAdvance (line 986) | @Test
    method readJsonValueInt (line 999) | @Test
    method readJsonValueMap (line 1006) | @Test
    method readJsonValueList (line 1013) | @Test
    method readJsonValueListMultipleTypes (line 1020) | @Test
    method readJsonValueNestedListInMap (line 1027) | @Test
    method skipName (line 1035) | @Test
    method skipNameFailUnknown (line 1045) | @Test
    method skipNameOnValueFails (line 1060) | @Test
    method emptyDocumentHasNextReturnsFalse (line 1071) | @Test
    method skipValueAtEndOfObjectFails (line 1078) | @Test
    method skipValueAtEndOfArrayFails (line 1094) | @Test
    method skipValueAtEndOfDocumentFails (line 1110) | @Test
    method basicPeekJson (line 1125) | @Test
    method peekJsonReader (line 1158) | @Test
    method readPeek12Steps (line 1171) | private void readPeek12Steps(JsonReader reader, int from, int until) t...
    method peekAfterPeek (line 1225) | @Test
    method peekAfterPromoteNameToValue (line 1234) | @Test
    method promoteStringNameToValue (line 1246) | @Test
    method promoteDoubleNameToValue (line 1256) | @Test
    method promoteLongNameToValue (line 1266) | @Test
    method promoteNullNameToValue (line 1276) | @Test
    method promoteBooleanNameToValue (line 1289) | @Test
    method promoteBooleanNameToValueCannotBeReadAsName (line 1302) | @Test
    method promoteSkippedNameToValue (line 1315) | @Test
    method promoteNameToValueAtEndOfObject (line 1324) | @Test
    method optionsStrings (line 1333) | @Test
    method nextSourceString (line 1348) | @Test
    method nextSourceLong (line 1359) | @Test
    method nextSourceNull (line 1370) | @Test
    method nextSourceBoolean (line 1381) | @Test
    method nextSourceObject (line 1392) | @Test
    method nextSourceArray (line 1403) | @Test
    method nextSourceStringBuffered (line 1418) | @Test
    method nextSourceNotConsumed (line 1431) | @Test
    method tags (line 1442) | @SuppressWarnings("rawtypes")
    method readValue (line 1470) | private void readValue(JsonReader reader, boolean peekJsonFirst) throw...

FILE: moshi/src/test/java/com/squareup/moshi/JsonUtf8ReaderTest.java
  class JsonUtf8ReaderTest (line 45) | public final class JsonUtf8ReaderTest {
    method readingDoesNotBuffer (line 46) | @Test
    method readObjectBuffer (line 61) | @Test
    method readObjectSource (line 74) | @Test
    method nullSource (line 87) | @Test
    method unescapingInvalidCharacters (line 96) | @Test
    method unescapingTruncatedCharacters (line 108) | @Test
    method unescapingTruncatedSequence (line 120) | @Test
    method strictNonFiniteDoublesWithSkipValue (line 132) | @Test
    method numberWithOctalPrefix (line 144) | @Test
    method peekingUnquotedStringsPrefixedWithBooleans (line 175) | @Test
    method malformedNumbers (line 190) | @Test
    method assertNotANumber (line 228) | private void assertNotANumber(String s) throws IOException {
    method peekingUnquotedStringsPrefixedWithIntegers (line 237) | @Test
    method peekLongMinValue (line 251) | @Test
    method peekLongMaxValue (line 260) | @Test
    method longLargerThanMaxLongThatWrapsAround (line 269) | @Test
    method longLargerThanMinLongThatWrapsAround (line 282) | @Test
    method peekLargerThanLongMaxValue (line 295) | @Test
    method precisionNotDiscarded (line 308) | @Test
    method peekLargerThanLongMinValue (line 321) | @Test
    method highPrecisionLong (line 335) | @Test
    method peekMuchLargerThanLongMinValue (line 344) | @Test
    method negativeZeroIsANumber (line 358) | @Test
    method numberToStringCoersion (line 365) | @Test
    method quotedNumberWithEscape (line 378) | @Test
    method mixedCaseLiterals (line 387) | @Test
    method missingValue (line 401) | @Test
    method prematureEndOfInput (line 413) | @Test
    method prematurelyClosed (line 426) | @SuppressWarnings("CheckReturnValue")
    method strictNameValueSeparator (line 458) | @Test
    method lenientNameValueSeparator (line 479) | @Test
    method strictNameValueSeparatorWithSkipValue (line 494) | @Test
    method commentsInStringValue (line 515) | @Test
    method strictComments (line 535) | @Test
    method lenientComments (line 562) | @Test
    method strictCommentsWithSkipValue (line 585) | @Test
    method strictUnquotedNames (line 612) | @Test
    method lenientUnquotedNames (line 623) | @Test
    method jsonIsSingleUnquotedString (line 631) | @Test
    method strictUnquotedNamesWithSkipValue (line 639) | @Test
    method strictSingleQuotedNames (line 650) | @Test
    method lenientSingleQuotedNames (line 661) | @Test
    method strictSingleQuotedNamesWithSkipValue (line 669) | @Test
    method strictUnquotedStrings (line 680) | @Test
    method strictUnquotedStringsWithSkipValue (line 691) | @Test
    method lenientUnquotedStrings (line 702) | @Test
    method lenientUnquotedStringsDelimitedByComment (line 710) | @Test
    method strictSingleQuotedStrings (line 719) | @Test
    method lenientSingleQuotedStrings (line 730) | @Test
    method strictSingleQuotedStringsWithSkipValue (line 738) | @Test
    method strictSemicolonDelimitedArray (line 749) | @Test
    method lenientSemicolonDelimitedArray (line 761) | @Test
    method strictSemicolonDelimitedArrayWithSkipValue (line 770) | @Test
    method strictSemicolonDelimitedNameValuePair (line 782) | @Test
    method lenientSemicolonDelimitedNameValuePair (line 795) | @Test
    method strictSemicolonDelimitedNameValuePairWithSkipValue (line 805) | @Test
    method strictUnnecessaryArraySeparators (line 818) | @Test
    method lenientUnnecessaryArraySeparators (line 855) | @Test
    method strictUnnecessaryArraySeparatorsWithSkipValue (line 887) | @Test
    method strictMultipleTopLevelValues (line 924) | @Test
    method lenientMultipleTopLevelValues (line 936) | @Test
    method strictMultipleTopLevelValuesWithSkipValue (line 948) | @Test
    method bomIgnoredAsFirstCharacterOfDocument (line 960) | @Test
    method bomForbiddenAsOtherCharacterInDocument (line 968) | @Test
    method failWithPosition (line 979) | @Test
    method failWithPositionGreaterThanBufferSize (line 984) | @Test
    method failWithPositionOverSlashSlashEndOfLineComment (line 990) | @Test
    method failWithPositionOverHashEndOfLineComment (line 995) | @Test
    method failWithPositionOverCStyleComment (line 1000) | @Test
    method failWithPositionOverQuotedString (line 1005) | @Test
    method failWithPositionOverUnquotedString (line 1010) | @Test
    method failWithEscapedNewlineCharacter (line 1015) | @Test
    method failWithPositionIsOffsetByBom (line 1020) | @Test
    method testFailWithPosition (line 1026) | private void testFailWithPosition(String message, String json) throws ...
    method failWithPositionDeepPath (line 1052) | @SuppressWarnings("CheckReturnValue")
    method failureMessagePathFromSkipName (line 1071) | @Test
    method strictVeryLongNumber (line 1086) | @Test
    method lenientVeryLongNumber (line 1098) | @Test
    method veryLongUnquotedLiteral (line 1110) | @Test
    method tooDeeplyNestedArrays (line 1120) | @Test
    method tooDeeplyNestedObjects (line 1136) | @Test
    method stringEndingInSlash (line 1161) | @Test
    method documentWithCommentEndingInSlash (line 1172) | @Test
    method stringWithLeadingSlash (line 1183) | @Test
    method unterminatedObject (line 1194) | @Test
    method veryLongQuotedString (line 1208) | @Test
    method veryLongUnquotedString (line 1220) | @Test
    method veryLongUnterminatedString (line 1233) | @Test
    method strictExtraCommasInMaps (line 1250) | @Test
    method lenientExtraCommasInMaps (line 1263) | @Test
    method malformedDocuments (line 1277) | @Test
    method unterminatedStringFailure (line 1326) | @Test
    method invalidEscape (line 1339) | @Test
    method lenientInvalidEscape (line 1351) | @Test
    method assertDocument (line 1359) | private void assertDocument(String document, Object... expectations) t...
    method nextSourceObject_withWhitespace (line 1395) | @Test
    method nextSourceLong_WithWhitespace (line 1406) | @Test
    method nextSourceStreams (line 1425) | @Test
    method nextSourceObjectAfterSelect (line 1445) | @Test
    method nextSourceObjectAfterPromoteNameToValue (line 1456) | @Test
    method nextSourcePath (line 1469) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/JsonUtf8WriterTest.java
  class JsonUtf8WriterTest (line 24) | public final class JsonUtf8WriterTest {
    method prettyPrintObject (line 25) | @Test
    method prettyPrintArray (line 65) | @Test
    method repeatedNameIgnored (line 104) | @Test
    method valueFromSource (line 116) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/JsonValueReaderTest.java
  class JsonValueReaderTest (line 35) | public final class JsonValueReaderTest {
    method array (line 36) | @Test
    method object (line 72) | @Test
    method nesting (line 116) | @Test
    method promoteNameToValue (line 169) | @Test
    method endArrayTooEarly (line 186) | @Test
    method endObjectTooEarly (line 201) | @Test
    method unsupportedType (line 214) | @Test
    method unsupportedKeyType (line 229) | @Test
    method nullKey (line 244) | @Test
    method unexpectedIntType (line 257) | @Test
    method unexpectedLongType (line 271) | @Test
    method unexpectedDoubleType (line 285) | @Test
    method unexpectedStringType (line 299) | @Test
    method unexpectedBooleanType (line 313) | @Test
    method unexpectedNullType (line 327) | @Test
    method skipRoot (line 341) | @Test
    method skipListValue (line 348) | @Test
    method skipObjectName (line 370) | @Test
    method skipObjectValue (line 398) | @Test
    method failOnUnknown (line 426) | @Test
    method close (line 440) | @Test
    method numberToStringCoersion (line 460) | @Test
    method tooDeeplyNestedArrays (line 474) | @Test
    method tooDeeplyNestedObjects (line 494) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/JsonValueWriterTest.java
  class JsonValueWriterTest (line 35) | public final class JsonValueWriterTest {
    method array (line 36) | @SuppressWarnings("unchecked")
    method object (line 51) | @Test
    method repeatedNameThrows (line 67) | @Test
    method valueLongEmitsLong (line 82) | @Test
    method valueDoubleEmitsDouble (line 97) | @Test
    method primitiveIntegerTypesEmitLong (line 153) | @Test
    method primitiveFloatingPointTypesEmitDouble (line 168) | @Test
    method otherNumberTypesEmitBigDecimal (line 180) | @Test
    method valueCustomNumberTypeEmitsLongOrBigDecimal (line 229) | @Test
    method valueFromSource (line 248) | @Test
    method stringNumber (line 270) | private Number stringNumber(final String s) {

FILE: moshi/src/test/java/com/squareup/moshi/JsonWriterPathTest.java
  class JsonWriterPathTest (line 30) | @RunWith(Parameterized.class)
    method parameters (line 34) | @Parameters(name = "{0}")
    method path (line 39) | @Test
    method arrayOfObjects (line 79) | @Test
    method arrayOfArrays (line 100) | @Test
    method objectPath (line 121) | @Test
    method nestedObjects (line 141) | @Test
    method arrayPath (line 167) | @Test
    method nestedArrays (line 189) | @Test
    method multipleTopLevelValuesInOneDocument (line 211) | @Test
    method skipNulls (line 225) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/JsonWriterTest.java
  class JsonWriterTest (line 39) | @RunWith(Parameterized.class)
    method parameters (line 43) | @Parameters(name = "{0}")
    method nullsValuesNotSerializedByDefault (line 48) | @Test
    method nullsValuesSerializedWhenConfigured (line 59) | @Test
    method topLevelBoolean (line 71) | @Test
    method topLevelNull (line 79) | @Test
    method topLevelInt (line 87) | @Test
    method topLevelDouble (line 95) | @Test
    method topLevelString (line 103) | @Test
    method invalidTopLevelTypes (line 111) | @Test
    method twoNames (line 121) | @Test
    method nameWithoutValue (line 133) | @Test
    method valueWithoutName (line 145) | @Test
    method multipleTopLevelValues (line 156) | @Test
    method badNestingObject (line 167) | @Test
    method badNestingArray (line 179) | @Test
    method nullName (line 191) | @Test
    method nullStringValue (line 202) | @Test
    method nonFiniteDoubles (line 213) | @Test
    method nonFiniteBoxedDoubles (line 234) | @Test
    method doubles (line 255) | @Test
    method longs (line 283) | @Test
    method numbers (line 298) | @Test
    method nullNumbers (line 318) | @Test
    method booleans (line 328) | @Test
    method boxedBooleans (line 338) | @Test
    method nulls (line 349) | @Test
    method strings (line 358) | @Test
    method unicodeLineBreaksEscaped (line 403) | @Test
    method emptyArray (line 412) | @Test
    method emptyObject (line 420) | @Test
    method objectsInArrays (line 428) | @Test
    method arraysInObjects (line 444) | @Test
    method deepNestingArrays (line 462) | @Test
    method tooDeeplyNestingArrays (line 474) | @Test
    method deepNestingObjects (line 490) | @Test
    method tooDeeplyNestingObjects (line 505) | @Test
    method lenientWriterPermitsMultipleTopLevelValues (line 522) | @Test
    method strictWriterDoesNotPermitMultipleTopLevelValues (line 536) | @Test
    method closedWriterThrowsOnStructure (line 548) | @Test
    method closedWriterThrowsOnName (line 576) | @Test
    method closedWriterThrowsOnValue (line 589) | @Test
    method closedWriterThrowsOnFlush (line 602) | @Test
    method writerCloseIsIdempotent (line 615) | @Test
    method nameNotInObjectFails (line 624) | @Test
    method missingValueInObjectIsANestingProblem (line 635) | @Test
    method nameInArrayIsANestingProblem (line 648) | @Test
    method danglingNameFails (line 660) | @Test
    method streamingValueInObject (line 673) | @Test
    method streamingValueInArray (line 689) | @Test
    method streamingValueTopLevel (line 700) | @Test
    method streamingValueTwiceBeforeCloseFails (line 707) | @Test
    method streamingValueTwiceAfterCloseFails (line 721) | @Test
    method streamingValueAndScalarValueFails (line 736) | @Test
    method streamingValueAndNameFails (line 750) | @Test
    method streamingValueInteractionAfterCloseFails (line 764) | @Test
    method streamingValueCloseIsIdempotent (line 780) | @Test
    method jsonValueTypes (line 795) | @Test
    method jsonValueIllegalTypes (line 832) | @Test
    method promoteStringNameToValue (line 869) | @Test
    method promoteDoubleNameToValue (line 880) | @Test
    method promoteLongNameToValue (line 891) | @Test
    method promoteNumberNameToValue (line 902) | @Test
    method promoteNullNameToValue (line 913) | @Test
    method promoteBooleanNameToValue (line 928) | @Test
    method promoteNameToValueCannotBeWrittenAsName (line 943) | @Test
    method promoteNameToValueAtEndOfObject (line 956) | @Test
    method tags (line 965) | @SuppressWarnings("rawtypes")

FILE: moshi/src/test/java/com/squareup/moshi/MoshiTest.java
  class MoshiTest (line 53) | @SuppressWarnings({"CheckReturnValue", "ResultOfMethodCallIgnored"})
    method booleanAdapter (line 55) | @Test
    method BooleanAdapter (line 81) | @Test
    method byteAdapter (line 94) | @Test
    method ByteAdapter (line 141) | @Test
    method charAdapter (line 152) | @Test
    method CharacterAdapter (line 232) | @Test
    method doubleAdapter (line 253) | @Test
    method DoubleAdapter (line 314) | @Test
    method floatAdapter (line 327) | @Test
    method FloatAdapter (line 388) | @Test
    method intAdapter (line 401) | @Test
    method IntegerAdapter (line 447) | @Test
    method longAdapter (line 458) | @Test
    method LongAdapter (line 504) | @Test
    method shortAdapter (line 515) | @Test
    method ShortAdapter (line 557) | @Test
    method stringAdapter (line 568) | @Test
    method upperBoundedWildcardsAreHandled (line 578) | @Test
    method lowerBoundedWildcardsAreNotHandled (line 588) | @Test
    method addNullFails (line 601) | @Test
    method customJsonAdapter (line 650) | @Test
    method classAdapterToObjectAndFromObject (line 661) | @Test
    method customJsonAdapterToObjectAndFromObject (line 676) | @Test
    method indent (line 691) | @Test
    method unindent (line 701) | @Test
    method composingJsonAdapterFactory (line 723) | @Test
    class Message (line 738) | static class Message {
    method registerJsonAdapterForAnnotatedType (line 743) | @Test
    method adapterLookupDisallowsNullType (line 770) | @Test
    method adapterLookupDisallowsNullAnnotations (line 781) | @Test
    method nextJsonAdapterDisallowsNullAnnotations (line 798) | @Test
    method delegatingJsonAdapterFactory (line 820) | @Test
    method listJsonAdapter (line 831) | @Test
    method setJsonAdapter (line 840) | @Test
    method collectionJsonAdapter (line 853) | @Test
    method collectionsDoNotKeepAnnotations (line 868) | @Test
    method noTypeAdapterForQualifiedPlatformType (line 886) | @Test
    method objectArray (line 903) | @Test
    method primitiveArray (line 911) | @Test
    method enumAdapter (line 919) | @Test
    method annotatedEnum (line 927) | @Test
    method invalidEnum (line 935) | @Test
    method invalidEnumHasCorrectPathInExceptionMessage (line 949) | @Test
    method nullEnum (line 967) | @Test
    method byDefaultUnknownFieldsAreIgnored (line 975) | @Test
    method failOnUnknownThrowsOnUnknownFields (line 984) | @Test
    method platformTypeThrows (line 996) | @Test
    method collectionClassesHaveClearErrorMessage (line 1028) | @Test
    method noCollectionErrorIfAdapterExplicitlyProvided (line 1060) | @Test
    class HasPlatformType (line 1079) | static final class HasPlatformType {
      class Wrapper (line 1082) | static final class Wrapper {
      class ListWrapper (line 1086) | static final class ListWrapper {
    method reentrantFieldErrorMessagesTopLevelMap (line 1091) | @Test
    method reentrantFieldErrorMessagesWrapper (line 1115) | @Test
    method reentrantFieldErrorMessagesListWrapper (line 1138) | @Test
    method qualifierWithElementsMayNotBeDirectlyRegistered (line 1162) | @Test
    method qualifierWithElements (line 1178) | @Test
    method adaptersRegisteredInOrderOfPrecedence (line 1196) | @Test
    method cachingJsonAdapters (line 1230) | @Test
    method newBuilder (line 1239) | @Test
    method referenceCyclesOnArrays (line 1249) | @Test
    method referenceCyclesOnObjects (line 1264) | @Test
    method referenceCyclesOnMixedTypes (line 1279) | @Test
    method duplicateKeyDisallowedInObjectType (line 1296) | @Test
    method duplicateKeysAllowedInCustomType (line 1311) | @Test
    method precedence (line 1319) | @Test
    method precedenceWithNewBuilder (line 1332) | @Test
    class AppendingAdapterFactory (line 1355) | static final class AppendingAdapterFactory implements JsonAdapter.Fact...
      method AppendingAdapterFactory (line 1358) | AppendingAdapterFactory(String suffix) {
      method create (line 1362) | @Override
    class Pizza (line 1381) | static class Pizza {
      method Pizza (line 1385) | Pizza(int diameter, boolean extraCheese) {
      method equals (line 1390) | @Override
      method hashCode (line 1397) | @Override
    class MealDeal (line 1403) | static class MealDeal {
      method MealDeal (line 1407) | MealDeal(Pizza pizza, String drink) {
      method equals (line 1412) | @Override
      method hashCode (line 1419) | @Override
    class PizzaAdapter (line 1425) | static class PizzaAdapter extends JsonAdapter<Pizza> {
      method fromJson (line 1426) | @Override
      method toJson (line 1445) | @Override
    class MealDealAdapterFactory (line 1454) | static class MealDealAdapterFactory implements JsonAdapter.Factory {
      method create (line 1455) | @Override
    class UppercaseAdapterFactory (line 1485) | static class UppercaseAdapterFactory implements JsonAdapter.Factory {
      method create (line 1486) | @Override
    type Roshambo (line 1508) | enum Roshambo {
    class Baguette (line 1521) | static class Baguette {
    class LocalizedBooleanAdapter (line 1529) | static class LocalizedBooleanAdapter extends JsonAdapter<Boolean> {
      method create (line 1532) | @Override
      method LocalizedBooleanAdapter (line 1549) | public LocalizedBooleanAdapter(String language) {
      method fromJson (line 1559) | @Override
      method toJson (line 1564) | @Override

FILE: moshi/src/test/java/com/squareup/moshi/ObjectAdapterTest.java
  class ObjectAdapterTest (line 43) | public final class ObjectAdapterTest {
    method toJsonUsesRuntimeType (line 44) | @Test
    method toJsonJavaLangObject (line 66) | @Test
    method fromJsonReturnsMapsAndLists (line 73) | @Test
    method fromJsonUsesDoublesForNumbers (line 96) | @Test
    method fromJsonDoesNotFailOnNullValues (line 103) | @Test
    method toJsonCoercesRuntimeTypeForCollections (line 114) | @Test
    method toJsonCoercesRuntimeTypeForLists (line 134) | @Test
    method toJsonCoercesRuntimeTypeForSets (line 154) | @Test
    method toJsonCoercesRuntimeTypeForMaps (line 174) | @Test
    method toJsonUsesTypeAdapters (line 189) | @Test
    method objectAdapterDelegatesStringNamesAndValues (line 212) | @Test
    method objectAdapterDelegatesObjects (line 238) | @Test
    method objectAdapterDelegatesLists (line 279) | @Test
    method objectAdapterDelegatesMaps (line 302) | @Test
    class Delivery (line 324) | static class Delivery {
    class Pizza (line 329) | static class Pizza {

FILE: moshi/src/test/java/com/squareup/moshi/PromoteNameToValueTest.java
  class PromoteNameToValueTest (line 29) | @RunWith(Parameterized.class)
    method parameters (line 33) | @Parameters(name = "{0}")
    method readerStringValue (line 38) | @Test
    method readerIntegerValue (line 53) | @Test
    method readerDoubleValue (line 68) | @Test
    method readerBooleanValue (line 83) | @Test
    method readerLongValue (line 108) | @Test
    method readerNullValue (line 123) | @Test
    method readerMultipleValueObject (line 148) | @Test
    method readerEmptyValueObject (line 165) | @Test
    method readerUnusedPromotionDoesntPersist (line 176) | @Test
    method readerUnquotedIntegerValue (line 192) | @Test
    method readerUnquotedLongValue (line 203) | @Test
    method readerUnquotedDoubleValue (line 214) | @Test
    method writerStringValue (line 225) | @Test
    method writerIntegerValue (line 239) | @Test
    method writerDoubleValue (line 253) | @Test
    method writerBooleanValue (line 267) | @Test
    method writerLongValue (line 288) | @Test
    method writerNullValue (line 302) | @Test
    method writerMultipleValueObject (line 324) | @Test
    method writerEmptyValueObject (line 340) | @Test
    method writerUnusedPromotionDoesntPersist (line 351) | @Test
    method writerSourceValueFails (line 367) | @Test
    method writerValueSinkFails (line 386) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/RecursiveTypesResolveTest.java
  class RecursiveTypesResolveTest (line 37) | public final class RecursiveTypesResolveTest {
    class Foo1 (line 39) | private static class Foo1<A> {
    class Foo2 (line 43) | private static class Foo2<B> {
    method recursiveResolveSimple (line 48) | @Test
    method doubleSupertype (line 58) | @Test
    method doubleSubtype (line 64) | @Test
    method superSubtype (line 69) | @Test
    method subSupertype (line 74) | @Test

FILE: moshi/src/test/java/com/squareup/moshi/TestUtil.java
  class TestUtil (line 21) | public final class TestUtil {
    method newReader (line 24) | public static JsonReader newReader(String json) {
    method repeat (line 29) | public static String repeat(char c, int count) {
    method repeat (line 35) | public static String repeat(String s, int count) {
    method TestUtil (line 43) | private TestUtil() {

FILE: moshi/src/test/java/com/squareup/moshi/TypesTest.java
  class TypesTest (line 39) | public final class TypesTest {
    method nextAnnotationsRequiresJsonAnnotation (line 53) | @Test
    method nextAnnotationsDoesNotContainReturnsNull (line 66) | @Test
    method nextAnnotationsReturnsDelegateAnnotations (line 75) | @Test
    method newParameterizedType (line 86) | @Test
    method newParameterizedType_missingTypeVars (line 97) | @Test
    method parameterizedTypeWithRequiredOwnerMissing (line 114) | @Test
    method parameterizedTypeWithUnnecessaryOwnerProvided (line 126) | @Test
    method parameterizedTypeWithIncorrectOwnerProvided (line 138) | @Test
    method arrayOf (line 150) | @Test
    method subtypeOf (line 160) | @Test
    method supertypeOf (line 167) | @Test
    method getFirstTypeArgument (line 174) | @Test
    method newParameterizedTypeObjectMethods (line 182) | @Test
    class A (line 200) | private static final class A {}
    class B (line 202) | private static final class B {}
    class C (line 204) | private static final class C {}
    class D (line 206) | private static final class D<T> {}
    class E (line 208) | private static final class E<T extends A, T2 extends B> {}
    method getFirstTypeArgument (line 214) | public static Type getFirstTypeArgument(Type type) throws Exception {
    type StringIntegerMap (line 226) | interface StringIntegerMap extends Map<String, Integer> {}
    method arrayComponentType (line 228) | @Test
    method collectionElementType (line 241) | @Test
    method mapKeyAndValueTypes (line 251) | @Test
    method propertiesTypes (line 261) | @Test
    method fixedVariablesTypes (line 269) | @Test
    method createJsonQualifierImplementation (line 277) | @SuppressWarnings("GetClassOnAnnotation") // Explicitly checking for p...
    method arrayEqualsGenericTypeArray (line 290) | @Test
    method parameterizedTypeMatchesClassWithGenericInfoFromReturn (line 298) | @Test
    method parameterizedAndWildcardTypesCannotHavePrimitiveArguments (line 317) | @Test
    method getFieldJsonQualifierAnnotations_privateFieldTest (line 345) | @Test
    method getFieldJsonQualifierAnnotations_publicFieldTest (line 354) | @Test
    method getFieldJsonQualifierAnnotations_unannotatedTest (line 363) | @Test
    method generatedJsonAdapterName_strings (line 371) | @Test
    method generatedJsonAdapterName_class (line 378) | @Test
    method generatedJsonAdapterName_class_missingJsonClass (line 384) | @Test
    class RecursiveTypeVars (line 400) | private static final class RecursiveTypeVars<T> {
    method recursiveTypeVariablesResolve (line 404) | @Test
    method recursiveTypeVariablesResolve1 (line 415) | @Test
    method recursiveTypeVariablesResolve2 (line 421) | @Test
    class TestType (line 427) | private static class TestType<X> {
    class TestType2 (line 431) | private static class TestType2<X, Y> {
    class TestJsonClass (line 435) | @JsonClass(generateAdapter = false)
    class TestNonJsonClass (line 438) | static class TestNonJsonClass {}
    class ClassWithAnnotatedFields (line 449) | static class ClassWithAnnotatedFields {

FILE: moshi/src/test/java/com/squareup/moshi/internal/ClassJsonAdapterTest.java
  class ClassJsonAdapterTest (line 38) | public final class ClassJsonAdapterTest {
    class BasicPizza (line 41) | static class BasicPizza {
    method basicClassAdapter (line 46) | @Test
    class PrivateFieldsPizza (line 59) | static class PrivateFieldsPizza {
    method privateFields (line 63) | @Test
    class BasePizza (line 75) | static class BasePizza {
    class DessertPizza (line 79) | static class DessertPizza extends BasePizza {
    method typeHierarchy (line 83) | @Test
    class BaseAbcde (line 96) | static class BaseAbcde {
    class ExtendsBaseAbcde (line 102) | static class ExtendsBaseAbcde extends BaseAbcde {
    method fieldsAreAlphabeticalAcrossFlattenedHierarchy (line 107) | @Test
    class StaticFields (line 127) | static class StaticFields {
    method staticFieldsOmitted (line 132) | @Test
    class TransientFields (line 144) | static class TransientFields {
    method transientFieldsOmitted (line 149) | @Test
    class IgnoredFields (line 162) | static class IgnoredFields {
    method ignoredFieldsOmitted (line 169) | @Test
    class BaseA (line 182) | static class BaseA {
    class ExtendsBaseA (line 186) | static class ExtendsBaseA extends BaseA {
    method fieldNameCollision (line 190) | @Test
    class NameCollision (line 205) | static class NameCollision {
    method jsonAnnotationNameCollision (line 212) | @Test
    class TransientBaseA (line 227) | static class TransientBaseA {
    class ExtendsTransientBaseA (line 231) | static class ExtendsTransientBaseA extends TransientBaseA {
    method fieldNameCollisionWithTransientFieldIsOkay (line 235) | @Test
    class NoArgConstructor (line 248) | static class NoArgConstructor {
      method NoArgConstructor (line 252) | NoArgConstructor() {
    method noArgConstructor (line 257) | @Test
    class NoArgConstructorThrowsCheckedException (line 264) | static class NoArgConstructorThrowsCheckedException {
      method NoArgConstructorThrowsCheckedException (line 265) | NoArgConstructorThrowsCheckedException() throws Exception {
    method noArgConstructorThrowsCheckedException (line 270) | @Test
    class NoArgConstructorThrowsUncheckedException (line 280) | static class NoArgConstructorThrowsUncheckedException {
      method NoArgConstructorThrowsUncheckedException (line 281) | NoArgConstructorThrowsUncheckedException() throws Exception {
    method noArgConstructorThrowsUncheckedException (line 286) | @Test
    class NoArgConstructorWithDefaultField (line 296) | static class NoArgConstructorWithDefaultField {
    method noArgConstructorFieldDefaultsHonored (line 301) | @Test
    class MagicConstructor (line 309) | static class MagicConstructor {
      method MagicConstructor (line 312) | public MagicConstructor(Void argument) {
    method magicConstructor (line 317) | @Test
    class MagicConstructorWithDefaultField (line 323) | static class MagicConstructorWithDefaultField {
      method MagicConstructorWithDefaultField (line 327) | public MagicConstructorWithDefaultField(Void argument) {
    method magicConstructorFieldDefaultsNotHonored (line 332) | @Test
    class NullRootObject (line 340) | static class NullRootObject {
    method nullRootObject (line 344) | @Test
    class NullFieldValue (line 353) | static class NullFieldValue {
    method nullFieldValues (line 357) | @Test
    class NonStatic (line 368) | class NonStatic {}
    method nonStaticNestedClassNotSupported (line 370) | @Test
    method anonymousClassNotSupported (line 384) | @Test
    method localClassNotSupported (line 403) | @Test
    type Interface (line 418) | interface Interface {}
    method interfaceNotSupported (line 420) | @Test
    class Abstract (line 425) | abstract static class Abstract {}
    method abstractClassNotSupported (line 427) | @Test
    class ExtendsPlatformClassWithPrivateField (line 441) | static class ExtendsPlatformClassWithPrivateField extends SimpleTimeZo...
      method ExtendsPlatformClassWithPrivateField (line 444) | public ExtendsPlatformClassWithPrivateField() {
    method platformSuperclassPrivateFieldIsExcluded (line 449) | @Test
    class ExtendsPlatformClassWithProtectedField (line 462) | static class ExtendsPlatformClassWithProtectedField extends ByteArrayO...
      method ExtendsPlatformClassWithProtectedField (line 465) | public ExtendsPlatformClassWithProtectedField() {
    method platformSuperclassProtectedFieldIsIncluded (line 470) | @Test
    class NamedFields (line 486) | static class NamedFields {
    method jsonAnnotationHonored (line 497) | @Test
    class Box (line 526) | static final class Box<T> {
      method Box (line 529) | Box(T data) {
    method parameterizedType (line 534) | @Test
    method toJson (line 548) | private <T> String toJson(Class<T> type, T value) throws IOException {
    method fromJson (line 566) | private <T> T fromJson(Class<T> type, String json) throws IOException {

FILE: moshi/src/test/java/com/squareup/moshi/internal/JsonValueSourceTest.java
  class JsonValueSourceTest (line 26) | public final class JsonValueSourceTest {
    method simpleValues (line 27) | @Test
    method braceMatching (line 34) | @Test
    method stringEscapes (line 41) | @Test
    method bracesInStrings (line 51) | @Test
    method unterminatedString (line 58) | @Test
    method unterminatedObject (line 67) | @Test
    method unterminatedArray (line 81) | @Test
    method lenientUnterminatedSingleQuotedString (line 95) | @Test
    method emptyStream (line 104) | @Test
    method lenientSingleQuotedStrings (line 123) | @Test
    method lenientCStyleComments (line 129) | @Test
    method lenientEndOfLineComments (line 138) | @Test
    method lenientSlashInToken (line 146) | @Test
    method lenientUnterminatedEndOfLineComment (line 151) | @Test
    method lenientUnterminatedCStyleComment (line 160) | @Test
    method discard (line 179) | @Test
    method jsonPrefix (line 191) | private String jsonPrefix(String string) throws IOException {

FILE: moshi/src/test/java/com/squareup/moshi/internal/LinkedHashTreeMapTest.java
  class LinkedHashTreeMapTest (line 27) | @SuppressWarnings("KotlinInternalInJava")
    method iterationOrder (line 29) | @Test
    method removeRootDoesNotDoubleUnlink (line 39) | @Test
    method putNullKeyFails (line 53) | @Test
    method putNonComparableKeyFails (line 63) | @Test
    method ContainsNonComparableKeyReturnsFalse (line 73) | @Test
    method containsNullKeyIsAlwaysFalse (line 80) | @Test
    method putOverrides (line 87) | @Test
    method emptyStringValues (line 100) | @Test
    method forceDoublingAndRehash (line 111) | @Test
    method clear (line 128) | @Test
    method equalsAndHashCode (line 139) | @Test
    method avlWalker (line 157) | @Test
    method assertAvlWalker (line 177) | private void assertAvlWalker(Node<String, String> root, String... valu...
    method avlBuilder (line 186) | @Test
    method assertAvlBuilder (line 214) | private void assertAvlBuilder(int size, String expected) {
    method doubleCapacity (line 224) | @Test
    method doubleCapacityAllNodesOnLeft (line 235) | @Test
    method node (line 254) | private Node<String, String> node(String value) {
    method node (line 258) | private Node<String, String> node(
    method assertTree (line 272) | private void assertTree(String expected, Node<?, ?> root) {
    method assertConsistent (line 277) | private void assertConsistent(Node<?, ?> node) {
    method toString (line 298) | private String toString(Node<?, ?> root) {

FILE: moshi/src/test/java/com/squareup/moshi/internal/MapJsonAdapterTest.java
  class MapJsonAdapterTest (line 38) | public final class MapJsonAdapterTest {
    method map (line 41) | @Test
    method mapWithNullKeyFailsToEmit (line 60) | @Test
    method emptyMap (line 73) | @Test
    method nullMap (line 84) | @Test
    method covariantValue (line 99) | @Test
    method orderIsRetained (line 121) | @Test
    method duplicatesAreForbidden (line 138) | @Test
    method mapWithNonStringKeys (line 151) | @Test
    method mapWithNonStringKeysToJsonObject (line 170) | @Test
    method booleanKeyTypeHasCoherentErrorMessage (line 187) | @Test
    class Key (line 210) | static final class Key {}
    method objectKeyTypeHasCoherentErrorMessage (line 212) | @Test
    method arrayKeyTypeHasCoherentErrorMessage (line 235) | @Test
    method toJson (line 259) | private <K, V> String toJson(Type keyType, Type valueType, Map<K, V> v...
    method mapAdapter (line 268) | @SuppressWarnings("unchecked") // It's the caller's responsibility to ...
    method fromJson (line 275) | private <K, V> Map<K, V> fromJson(Type keyType, Type valueType, String...
Condensed preview — 183 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,291K chars).
[
  {
    "path": ".editorconfig",
    "chars": 174,
    "preview": "root = true\n\n[*]\nindent_size = 2\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\nmax_line_le"
  },
  {
    "path": ".gitattributes",
    "chars": 52,
    "preview": "* text=auto eol=lf\n\n*.bat text eol=crlf\n*.jar binary"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 420,
    "preview": "---\nname: Bug report\nabout: A reproducible problem\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\nGood bug reports include a "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 198,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Question?\n    url: https://stackoverflow.com/questions/tagged/moshi"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 345,
    "preview": "---\nname: Feature request\nabout: Suggest an idea\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\nStart by telling us w"
  },
  {
    "path": ".github/renovate.json5",
    "chars": 657,
    "preview": "{\n  $schema: 'https://docs.renovatebot.com/renovate-schema.json',\n  extends: [\n    'config:recommended',\n  ],\n  ignorePr"
  },
  {
    "path": ".github/workflows/.java-version",
    "chars": 3,
    "preview": "25\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 1202,
    "preview": "name: CI\n\non: [push, pull_request]\n\njobs:\n  build:\n    name: 'Test Mode ${{ matrix.kotlin-test-mode }}'\n    runs-on: ubu"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 1392,
    "preview": "name: release\n\non:\n  push:\n    tags:\n      - '**'\n\njobs:\n  release:\n    runs-on: macos-latest\n\n    steps:\n      - uses: "
  },
  {
    "path": ".gitignore",
    "chars": 232,
    "preview": ".classpath\n.project\n.settings\neclipsebin\n\nbin\ngen\nbuild\nout\nlib\n\ntarget\npom.xml.*\nrelease.properties\ndependency-reduced-"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 31796,
    "preview": "# Change Log\n\n## Unreleased\n\n* None yet.\n\n\n## [2.0.0-alpha.1] - 2026-01-28\n\n* Refuse `j$.*` types from Android library d"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 676,
    "preview": "Contributing\n============\n\nIf you would like to contribute code to Moshi you can do so through GitHub by\nforking the rep"
  },
  {
    "path": "LICENSE.txt",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "README.md",
    "chars": 29762,
    "preview": "Moshi\n=====\n\nMoshi is a modern JSON library for Android, Java and Kotlin. It makes it easy to parse JSON into Java and K"
  },
  {
    "path": "build.gradle.kts",
    "chars": 5701,
    "preview": "import com.diffplug.gradle.spotless.JavaExtension\nimport com.vanniktech.maven.publish.MavenPublishBaseExtension\nimport j"
  },
  {
    "path": "examples/build.gradle.kts",
    "chars": 410,
    "preview": "import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n  kotlin(\"jvm\")\n  alias(libs.plugins.ksp)\n}\n\ndependenc"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/ByteStrings.java",
    "chars": 1940,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/CardAdapter.java",
    "chars": 1499,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/CustomAdapterFactory.java",
    "chars": 4000,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/CustomAdapterWithDelegate.java",
    "chars": 2194,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/CustomFieldName.java",
    "chars": 1229,
    "preview": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/CustomQualifier.java",
    "chars": 2053,
    "preview": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/CustomTypeAdapter.java",
    "chars": 1441,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/DefaultOnDataMismatchAdapter.java",
    "chars": 2479,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/FallbackEnum.java",
    "chars": 4241,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/FromJsonWithoutStrings.java",
    "chars": 2710,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/IncludeNullsForAnnotatedTypes.java",
    "chars": 2518,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/IncludeNullsForOneType.java",
    "chars": 2145,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/JsonString.kt",
    "chars": 2219,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/MultipleFormats.java",
    "chars": 3408,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/ReadAndWriteRfc3339Dates.java",
    "chars": 2359,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/ReadJson.java",
    "chars": 1708,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/ReadJsonList.java",
    "chars": 1750,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/ReadJsonListKt.kt",
    "chars": 1287,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/RecoverFromTypeMismatch.java",
    "chars": 1419,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/Unwrap.java",
    "chars": 3291,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/WriteJson.java",
    "chars": 1559,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/models/BlackjackHand.java",
    "chars": 1037,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/models/Card.java",
    "chars": 903,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/models/Player.java",
    "chars": 1026,
    "preview": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/models/Suit.java",
    "chars": 787,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/models/Tournament.java",
    "chars": 1034,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "examples/src/main/java/com/squareup/moshi/recipes/package-info.java",
    "chars": 111,
    "preview": "/** Moshi code samples. */\n@javax.annotation.ParametersAreNonnullByDefault\npackage com.squareup.moshi.recipes;\n"
  },
  {
    "path": "gradle/libs.versions.toml",
    "chars": 2111,
    "preview": "[versions]\nautoService = \"1.1.1\"\njdk = \"21\"\njvmTarget = \"1.8\"\nkotlin = \"2.3.20\"\nkotlinCompileTesting = \"0.12.1\"\nkotlinpo"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 252,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "gradle.properties",
    "chars": 143,
    "preview": "# Memory for Dokka https://github.com/Kotlin/dokka/issues/1405\norg.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\n\nVERSI"
  },
  {
    "path": "gradlew",
    "chars": 8631,
    "preview": "#!/bin/sh\n\n#\n# Copyright © 2015 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "gradlew.bat",
    "chars": 2896,
    "preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
  },
  {
    "path": "moshi/build.gradle.kts",
    "chars": 1936,
    "preview": "import org.gradle.jvm.tasks.Jar\nimport org.jetbrains.kotlin.gradle.dsl.JvmTarget\nimport org.jetbrains.kotlin.gradle.dsl."
  },
  {
    "path": "moshi/gradle.properties",
    "chars": 52,
    "preview": "kotlin.build.archivesTaskOutputAsFriendModule=false\n"
  },
  {
    "path": "moshi/japicmp/build.gradle.kts",
    "chars": 2608,
    "preview": "import me.champeau.gradle.japicmp.JapicmpTask\n\nplugins {\n  `java-library`\n  id(\"me.champeau.gradle.japicmp\")\n}\n\nval base"
  },
  {
    "path": "moshi/records-tests/build.gradle.kts",
    "chars": 376,
    "preview": "plugins { `java-library` }\n\njava { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } }\n\ntasks.withType<JavaC"
  },
  {
    "path": "moshi/records-tests/src/test/java/com/squareup/moshi/records/RecordsTest.java",
    "chars": 10047,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/-JsonUtf8Reader.kt",
    "chars": 36424,
    "preview": "/*\n * Copyright (C) 2010 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/-JsonUtf8Writer.kt",
    "chars": 11911,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/-JsonValueReader.kt",
    "chars": 12325,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/-JsonValueWriter.kt",
    "chars": 8878,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/-MoshiKotlinExtensions.kt",
    "chars": 2138,
    "preview": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/-MoshiKotlinTypesExtensions.kt",
    "chars": 3125,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/FromJson.kt",
    "chars": 804,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/Json.kt",
    "chars": 1760,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/JsonAdapter.kt",
    "chars": 9901,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/JsonClass.kt",
    "chars": 3395,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/JsonDataException.kt",
    "chars": 1605,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/JsonEncodingException.kt",
    "chars": 803,
    "preview": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/JsonQualifier.kt",
    "chars": 941,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/JsonReader.kt",
    "chars": 23249,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/JsonWriter.kt",
    "chars": 16577,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/Moshi.kt",
    "chars": 15089,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/ToJson.kt",
    "chars": 802,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/Types.kt",
    "chars": 11164,
    "preview": "/*\n * Copyright (C) 2008 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/AdapterMethodsFactory.kt",
    "chars": 14877,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/ArrayJsonAdapter.kt",
    "chars": 3307,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/ClassFactory.kt",
    "chars": 4861,
    "preview": "/*\n * Copyright (C) 2011 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/ClassJsonAdapter.kt",
    "chars": 8015,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/CollectionJsonAdapter.kt",
    "chars": 3077,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/JsonScope.kt",
    "chars": 2931,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/JsonValueSource.kt",
    "chars": 7045,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/KotlinReflectTypes.kt",
    "chars": 4806,
    "preview": "/*\n * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.\n * Use of this source code is g"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/LinkedHashTreeMap.kt",
    "chars": 23461,
    "preview": "package com.squareup.moshi.internal\n\nimport com.squareup.moshi.internal.LinkedHashTreeMap.Node\nimport java.io.Serializab"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/MapJsonAdapter.kt",
    "chars": 2895,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/NonNullJsonAdapter.kt",
    "chars": 1405,
    "preview": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/NullSafeJsonAdapter.kt",
    "chars": 1259,
    "preview": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/RecordJsonAdapter.kt",
    "chars": 1327,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/StandardJsonAdapters.kt",
    "chars": 11374,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/internal/Util.kt",
    "chars": 24728,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/java/com/squareup/moshi/package-info.java",
    "chars": 134,
    "preview": "/** Moshi is modern JSON library for Android and Java. */\n@javax.annotation.ParametersAreNonnullByDefault\npackage com.sq"
  },
  {
    "path": "moshi/src/main/java16/com/squareup/moshi/internal/RecordJsonAdapter.kt",
    "chars": 5798,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/main/resources/META-INF/proguard/moshi.pro",
    "chars": 954,
    "preview": "# JSR 305 annotations are for embedding nullability information.\n-dontwarn javax.annotation.**\n\n-keepclasseswithmembers "
  },
  {
    "path": "moshi/src/test/java/android/util/Pair.java",
    "chars": 650,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/AdapterMethodsTest.java",
    "chars": 30642,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/CircularAdaptersTest.java",
    "chars": 5539,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/DeferredAdapterTest.java",
    "chars": 4152,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/FlattenTest.java",
    "chars": 8967,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonAdapterTest.java",
    "chars": 11136,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonCodecFactory.java",
    "chars": 5898,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonQualifiersTest.java",
    "chars": 14412,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonReaderPathTest.java",
    "chars": 7871,
    "preview": "/*\n * Copyright (C) 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java",
    "chars": 48867,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonUtf8ReaderTest.java",
    "chars": 44584,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonUtf8WriterTest.java",
    "chars": 3828,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonValueReaderTest.java",
    "chars": 16215,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonValueWriterTest.java",
    "chars": 9518,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonWriterPathTest.java",
    "chars": 8304,
    "preview": "/*\n * Copyright (C) 2014 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/JsonWriterTest.java",
    "chars": 27121,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/KotlinExtensionsTest.kt",
    "chars": 2928,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/MoshiTest.java",
    "chars": 54127,
    "preview": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/MoshiTesting.kt",
    "chars": 899,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/ObjectAdapterTest.java",
    "chars": 11027,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/PromoteNameToValueTest.java",
    "chars": 13227,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/RecursiveTypesResolveTest.java",
    "chars": 2479,
    "preview": "/*\n * Copyright (C) 2017 Gson Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/TestUtil.java",
    "chars": 1330,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/TypesTest.java",
    "chars": 16530,
    "preview": "/*\n * Copyright (C) 2010 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/internal/ClassJsonAdapterTest.java",
    "chars": 17647,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/internal/JsonValueSourceTest.java",
    "chars": 6149,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/internal/KotlinReflectTypesTest.kt",
    "chars": 6448,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/internal/LinkedHashTreeMapTest.java",
    "chars": 10052,
    "preview": "/*\n * Copyright (C) 2012 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi/src/test/java/com/squareup/moshi/internal/MapJsonAdapterTest.java",
    "chars": 9194,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-adapters/README.md",
    "chars": 1084,
    "preview": "Adapters\n===================\n\nPrebuilt Moshi `JsonAdapter`s for various things, such as `Rfc3339DateJsonAdapter` for par"
  },
  {
    "path": "moshi-adapters/build.gradle.kts",
    "chars": 388,
    "preview": "import org.gradle.jvm.tasks.Jar\n\nplugins {\n  kotlin(\"jvm\")\n  id(\"com.vanniktech.maven.publish\")\n  id(\"org.jetbrains.dokk"
  },
  {
    "path": "moshi-adapters/japicmp/build.gradle.kts",
    "chars": 796,
    "preview": "import me.champeau.gradle.japicmp.JapicmpTask\n\nplugins {\n  `java-library`\n  id(\"me.champeau.gradle.japicmp\")\n}\n\nval base"
  },
  {
    "path": "moshi-adapters/src/main/java/com/squareup/moshi/Rfc3339DateJsonAdapter.kt",
    "chars": 1402,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-adapters/src/main/java/com/squareup/moshi/adapters/EnumJsonAdapter.kt",
    "chars": 3492,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-adapters/src/main/java/com/squareup/moshi/adapters/Iso8601Utils.kt",
    "chars": 9710,
    "preview": "/*\n * Copyright (C) 2011 FasterXML, LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may"
  },
  {
    "path": "moshi-adapters/src/main/java/com/squareup/moshi/adapters/PolymorphicJsonAdapterFactory.kt",
    "chars": 9453,
    "preview": "/*\n * Copyright (C) 2011 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may no"
  },
  {
    "path": "moshi-adapters/src/main/java/com/squareup/moshi/adapters/Rfc3339DateJsonAdapter.kt",
    "chars": 1958,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-adapters/src/test/java/com/squareup/moshi/adapters/EnumJsonAdapterTest.java",
    "chars": 2951,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-adapters/src/test/java/com/squareup/moshi/adapters/PolymorphicJsonAdapterFactoryTest.java",
    "chars": 19254,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-adapters/src/test/java/com/squareup/moshi/adapters/Rfc3339DateJsonAdapterTest.java",
    "chars": 5223,
    "preview": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin/build.gradle.kts",
    "chars": 435,
    "preview": "import org.gradle.jvm.tasks.Jar\n\nplugins {\n  kotlin(\"jvm\")\n  id(\"com.vanniktech.maven.publish\")\n  id(\"org.jetbrains.dokk"
  },
  {
    "path": "moshi-kotlin/src/main/java/com/squareup/moshi/KotlinJsonAdapterFactory.kt",
    "chars": 986,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin/src/main/java/com/squareup/moshi/kotlin/reflect/IndexedParameterMap.kt",
    "chars": 941,
    "preview": "package com.squareup.moshi.kotlin.reflect\n\n/** A simple [Map] that uses parameter indexes instead of sorting or hashing."
  },
  {
    "path": "moshi-kotlin/src/main/java/com/squareup/moshi/kotlin/reflect/Invokable.kt",
    "chars": 2647,
    "preview": "package com.squareup.moshi.kotlin.reflect\n\nimport com.squareup.moshi.internal.DEFAULT_CONSTRUCTOR_MARKER\nimport java.lan"
  },
  {
    "path": "moshi-kotlin/src/main/java/com/squareup/moshi/kotlin/reflect/JvmDescriptors.kt",
    "chars": 4815,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin/src/main/java/com/squareup/moshi/kotlin/reflect/JvmSignatureSearcher.kt",
    "chars": 2133,
    "preview": "package com.squareup.moshi.kotlin.reflect\n\nimport java.lang.reflect.Field\nimport java.lang.reflect.Method\nimport kotlin."
  },
  {
    "path": "moshi-kotlin/src/main/java/com/squareup/moshi/kotlin/reflect/KmExecutable.kt",
    "chars": 6872,
    "preview": "package com.squareup.moshi.kotlin.reflect\n\nimport java.lang.reflect.Constructor\nimport java.lang.reflect.Method\nimport j"
  },
  {
    "path": "moshi-kotlin/src/main/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterFactory.kt",
    "chars": 15773,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin/src/main/java/com/squareup/moshi/kotlin/reflect/KtTypes.kt",
    "chars": 6889,
    "preview": "/*\n * Copyright (C) 2025 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin/src/main/resources/META-INF/com.android.tools/proguard/moshi-metadata-reflect.pro",
    "chars": 816,
    "preview": "# When editing this file, update the following files as well:\n# - META-INF/com.android.tools/r8-from-1.6.0/moshi-metadat"
  },
  {
    "path": "moshi-kotlin/src/main/resources/META-INF/com.android.tools/r8-from-1.6.0/moshi-metadata-reflect.pro",
    "chars": 661,
    "preview": "# When editing this file, update the following files as well:\n# - META-INF/com.android.tools/proguard/moshi-kotlin.pro\n#"
  },
  {
    "path": "moshi-kotlin/src/main/resources/META-INF/com.android.tools/r8-upto-1.6.0/moshi-metadata-reflect.pro",
    "chars": 941,
    "preview": "# When editing this file, update the following files as well:\n# - META-INF/com.android.tools/proguard/moshi-kotlin.pro\n#"
  },
  {
    "path": "moshi-kotlin/src/test/java/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt",
    "chars": 1212,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/build.gradle.kts",
    "chars": 1605,
    "preview": "import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n  kotlin(\"jvm\")\n  id(\"com.google.devtools.ksp\")\n  id(\""
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/AdapterGenerator.kt",
    "chars": 32750,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/DelegateKey.kt",
    "chars": 3974,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/InternalMoshiCodegenApi.kt",
    "chars": 921,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/Options.kt",
    "chars": 2193,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/ProguardRules.kt",
    "chars": 4226,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/PropertyGenerator.kt",
    "chars": 2990,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TargetConstructor.kt",
    "chars": 993,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TargetParameter.kt",
    "chars": 1073,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TargetProperty.kt",
    "chars": 1312,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TargetType.kt",
    "chars": 1235,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/TypeRenderer.kt",
    "chars": 4259,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/kotlintypes.kt",
    "chars": 8796,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/api/typeAliasUnwrapping.kt",
    "chars": 2598,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/AppliedType.kt",
    "chars": 2446,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/JsonClassSymbolProcessorProvider.kt",
    "chars": 7294,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/KspUtil.kt",
    "chars": 5026,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/MoshiApiUtil.kt",
    "chars": 3263,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/TargetTypes.kt",
    "chars": 11366,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/main/java/com/squareup/moshi/kotlin/codegen/ksp/shadedUtil.kt",
    "chars": 9999,
    "preview": "/*\n * Copyright 2020 Google LLC\n * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.\n *"
  },
  {
    "path": "moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/JavaSuperclass.java",
    "chars": 836,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-codegen/src/test/java/com/squareup/moshi/kotlin/codegen/ksp/JsonClassSymbolProcessorTest.kt",
    "chars": 29291,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/build.gradle.kts",
    "chars": 1348,
    "preview": "import TestMode.KSP\nimport TestMode.REFLECT\nimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n  kotlin(\""
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/build.gradle.kts",
    "chars": 1510,
    "preview": "import TestMode.KSP\nimport TestMode.REFLECT\nimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n  kotlin(\""
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/CompileOnlyTests.kt",
    "chars": 4649,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/ComplexGenericsInheritanceTest.kt",
    "chars": 4281,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/DefaultConstructorTest.kt",
    "chars": 2317,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest.kt",
    "chars": 42319,
    "preview": "/*\n * Copyright (C) 2018 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter.kt",
    "chars": 1226,
    "preview": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/LooksLikeAClass/ClassInPackageThatLooksLikeAClass.kt",
    "chars": 874,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MixingReflectAndCodeGen.kt",
    "chars": 1664,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MoshiKspTest.kt",
    "chars": 1640,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/MultipleMasksTest.kt",
    "chars": 3601,
    "preview": "/*\n * Copyright (C) 2019 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/codegen-only/src/test/kotlin/com/squareup/moshi/kotlin/codegen/annotation/UppercaseInAnnotationPackage.kt",
    "chars": 1130,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/extra-moshi-test-module/build.gradle.kts",
    "chars": 78,
    "preview": "plugins { kotlin(\"jvm\") }\n\ndependencies { implementation(project(\":moshi\")) }\n"
  },
  {
    "path": "moshi-kotlin-tests/extra-moshi-test-module/src/main/kotlin/com/squareup/moshi/kotlin/codegen/test/extra/AbstractClassInModuleA.kt",
    "chars": 1254,
    "preview": "/*\n * Copyright (C) 2021 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/src/test/kotlin/com/squareup/moshi/kotlin/DualKotlinTest.kt",
    "chars": 26160,
    "preview": "/*\n * Copyright (C) 2020 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "moshi-kotlin-tests/src/test/kotlin/com/squareup/moshi/kotlin/reflect/KotlinJsonAdapterTest.kt",
    "chars": 36165,
    "preview": "/*\n * Copyright (C) 2017 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may n"
  },
  {
    "path": "releasing.md",
    "chars": 1123,
    "preview": "# Releasing\n\nCutting a Release\n-----------------\n\n1. Update the `CHANGELOG.md`:\n   1. Change the `Unreleased` header to "
  },
  {
    "path": "settings.gradle.kts",
    "chars": 477,
    "preview": "pluginManagement {\n  repositories {\n    mavenCentral()\n    gradlePluginPortal()\n  }\n}\n\nrootProject.name = \"moshi-root\"\n\n"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the square/moshi GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 183 files (1.2 MB), approximately 299.4k tokens, and a symbol index with 1070 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!