Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/test-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
- scala3-upickle,schema-scala3-upickle
- elixir,schema-elixir,graphql-elixir
- elm,schema-elm
- gleam,schema-gleam
- comment-injection-treesitter,comment-injection-typescript,comment-injection-typescript-zod,comment-injection-typescript-effect-schema

# Not yet started
Expand Down Expand Up @@ -205,6 +206,15 @@ jobs:
elixir-version: "1.15.7"
otp-version: "26.0"

- name: Install Gleam
if: ${{ contains(matrix.fixture, 'gleam') }}
uses: erlef/setup-beam@v1
with:
# gleam_json delegates to OTP's built-in json module, which
# requires OTP 27 or newer.
otp-version: "27.0"
gleam-version: "1.14.0"

- run: QUICKTEST=true FIXTURE=${{ matrix.fixture }} npm run test:fixtures
env:
CPUs: ${{ contains(matrix.fixture, 'scala3') && '2' || '0' }}
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
| [Java](https://app.quicktype.io/#l=java) | [Scala](https://app.quicktype.io/#l=scala3) | [TypeScript](https://app.quicktype.io/#l=ts) | [Swift](https://app.quicktype.io/#l=swift) | [Objective-C](https://app.quicktype.io/#l=objc) | [Elm](https://app.quicktype.io/#l=elm) |
| ---------------------------------------- | ------------------------------------------- | -------------------------------------------- | ------------------------------------------ | ----------------------------------------------- | -------------------------------------- |

| [JSON Schema](https://app.quicktype.io/#l=schema) | [Pike](https://app.quicktype.io/#l=pike) | [Prop-Types](https://app.quicktype.io/#l=javascript-prop-types) | [Haskell](https://app.quicktype.io/#l=haskell) | [PHP](https://app.quicktype.io/#l=php) |
| ------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------- |
| [JSON Schema](https://app.quicktype.io/#l=schema) | [Pike](https://app.quicktype.io/#l=pike) | [Prop-Types](https://app.quicktype.io/#l=javascript-prop-types) | [Haskell](https://app.quicktype.io/#l=haskell) | [PHP](https://app.quicktype.io/#l=php) | [Gleam](https://app.quicktype.io/#l=gleam) |
| ------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------- | ------------------------------------------ |

_Missing your favorite language? Please implement it!_

Expand Down
14 changes: 14 additions & 0 deletions packages/quicktype-core/src/Run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ const defaultOptions: NonInferenceOptions = {
};

export interface RunContext {
/**
* Whether JSON inference merges `integer` and `double` into `double`
* when samples mix them. See
* `TargetLanguage.infersUnionsWithBothNumberTypes`.
*/
conflateNumbersInInference: boolean;
debugPrintReconstitution: boolean;
debugPrintSchemaResolving: boolean;
debugPrintTransformations: boolean;
Expand Down Expand Up @@ -190,6 +196,14 @@ class Run implements RunContext {
return mapping;
}

public get conflateNumbersInInference(): boolean {
const targetLanguage = getTargetLanguage(this._options.lang);
return !(
targetLanguage.supportsUnionsWithBothNumberTypes &&
targetLanguage.infersUnionsWithBothNumberTypes
);
}

public get debugPrintReconstitution(): boolean {
return this._options.debugPrintReconstitution === true;
}
Expand Down
18 changes: 18 additions & 0 deletions packages/quicktype-core/src/TargetLanguage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,24 @@ export abstract class TargetLanguage<
return false;
}

/**
* Whether inference from JSON samples keeps `integer` and `double` as
* separate union members when one value position mixes them, so that
* `[1, 1.5]` infers `integer | double` instead of `double`.
*
* Off by default: JSON does not distinguish `1` from `1.0`, and most
* languages have a single numeric type that fits both. A language whose
* integer and floating-point types are disjoint at runtime (Gleam's
* `Int` and `Float`) opts in so a whole number is not widened to a float.
*
* Only meaningful together with `supportsUnionsWithBothNumberTypes`;
* without it, later rewrites conflate the inferred union back into
* `double`.
*/
public get infersUnionsWithBothNumberTypes(): boolean {
return false;
}

public get supportsFullObjectType(): boolean {
return false;
}
Expand Down
5 changes: 3 additions & 2 deletions packages/quicktype-core/src/input/Inference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export class TypeInference {
private readonly _typeBuilder: TypeBuilder,
private readonly _inferMaps: boolean,
private readonly _inferEnums: boolean,
private readonly _conflateNumbers: boolean,
) {}

private addValuesToAccumulator(
Expand Down Expand Up @@ -325,7 +326,7 @@ export class TypeInference {
const accumulator = new UnionAccumulator<
NestedValueArray,
NestedValueArray
>(true);
>(this._conflateNumbers);
this.addValuesToAccumulator(valueArray, accumulator);
return accumulator;
}
Expand Down Expand Up @@ -398,7 +399,7 @@ export class TypeInference {
const accumulator = new UnionAccumulator<
NestedValueArray,
NestedValueArray
>(true);
>(this._conflateNumbers);
for (const key of propertyNames) {
this.addValuesToAccumulator(propertyValues[key], accumulator);
}
Expand Down
3 changes: 2 additions & 1 deletion packages/quicktype-core/src/input/Inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export class JSONInput<T> implements Input<JSONSourceData<T>> {
}

public addTypesSync(
_ctx: RunContext,
ctx: RunContext,
typeBuilder: TypeBuilder,
inferMaps: boolean,
inferEnums: boolean,
Expand All @@ -183,6 +183,7 @@ export class JSONInput<T> implements Input<JSONSourceData<T>> {
typeBuilder,
inferMaps,
inferEnums,
ctx.conflateNumbersInInference,
);

for (const [name, { samples, description }] of this._topLevels) {
Expand Down
2 changes: 2 additions & 0 deletions packages/quicktype-core/src/language/All.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CrystalTargetLanguage } from "./Crystal/index.js";
import { DartTargetLanguage } from "./Dart/index.js";
import { ElixirTargetLanguage } from "./Elixir/index.js";
import { ElmTargetLanguage } from "./Elm/index.js";
import { GleamTargetLanguage } from "./Gleam/index.js";
import { GoTargetLanguage } from "./Golang/index.js";
import { HaskellTargetLanguage } from "./Haskell/index.js";
import { JSONSchemaTargetLanguage } from "./JSONSchema/index.js";
Expand Down Expand Up @@ -44,6 +45,7 @@ export const all = [
new ElixirTargetLanguage(),
new ElmTargetLanguage(),
new FlowTargetLanguage(),
new GleamTargetLanguage(),
new GoTargetLanguage(),
new HaskellTargetLanguage(),
new JavaTargetLanguage(),
Expand Down
Loading