Skip to content

fix: alphabetizeProperties option #2700

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
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
256 changes: 7 additions & 249 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,254 +1,12 @@
![](https://raw.githubusercontent.com/quicktype/quicktype/master/media/quicktype-logo.svg?sanitize=true)
This repo is forked from: https://github.com/glideapps/quicktype.

[![npm version](https://badge.fury.io/js/quicktype.svg)](https://badge.fury.io/js/quicktype)
![Build status](https://github.com/quicktype/quicktype/actions/workflows/master.yaml/badge.svg)
Original work is licensed under the Apache License, Version 2.0.

`quicktype` generates strongly-typed models and serializers from JSON, JSON Schema, TypeScript, and [GraphQL queries](https://blog.quicktype.io/graphql-with-quicktype/), making it a breeze to work with JSON type-safely in many programming languages.
Modifications on package `quicktype-core` have been made by Huajie Zhang and include:

- [Try `quicktype` in your browser](https://app.quicktype.io).
- Read ['A first look at quicktype'](http://blog.quicktype.io/first-look/) for more introduction.
- If you have any questions, check out the [FAQ](FAQ.md) first.
- Fix the issue that option `alphabetizeProperties` does not work for convert from JSON schema to typescript scenario
- Added option `jsonStringifySpaceNum` to control the space size for typescript converter that convert the JSON object to string

### Supported Inputs
Modified version maintained at: https://github.com/jayzhang/quicktype

| JSON | JSON API URLs | [JSON Schema](https://app.quicktype.io/#s=coordinate) |
| ---- | ------------- | ----------------------------------------------------- |

| TypeScript | GraphQL queries |
| ---------- | --------------- |

### Target Languages

| [Ruby](https://app.quicktype.io/#l=ruby) | [JavaScript](https://app.quicktype.io/#l=js) | [Flow](https://app.quicktype.io/#l=flow) | [Rust](https://app.quicktype.io/#l=rust) | [Kotlin](https://app.quicktype.io/#l=kotlin) |
| ---------------------------------------- | -------------------------------------------- | ---------------------------------------- | ---------------------------------------- | -------------------------------------------- |

| [Dart](https://app.quicktype.io/#l=dart) | [Python](https://app.quicktype.io/#l=python) | [C#](https://app.quicktype.io/#l=cs) | [Go](https://app.quicktype.io/#l=go) | [C++](https://app.quicktype.io/#l=cpp) |
| ---------------------------------------- | -------------------------------------------- | ------------------------------------ | ------------------------------------ | -------------------------------------- |

| [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) |
| ------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------- |

_Missing your favorite language? Please implement it!_

## Installation

There are many ways to use `quicktype`. [app.quicktype.io](https://app.quicktype.io) is the most powerful and complete UI. The web app also works offline and doesn't send your sample data over the Internet, so paste away!

For the best CLI, we recommend installing `quicktype` globally via `npm`:

```bash
npm install -g quicktype
```

## Using `quicktype`

```bash
# Run quicktype without arguments for help and options
quicktype

# quicktype a simple JSON object in C#
echo '{ "name": "David" }' | quicktype -l csharp

# quicktype a top-level array and save as Go source
echo '[1, 2, 3]' | quicktype -o ints.go

# quicktype a sample JSON file in Swift
quicktype person.json -o Person.swift

# A verbose way to do the same thing
quicktype \
--src person.json \
--src-lang json \
--lang swift \
--top-level Person \
--out Person.swift

# quicktype a directory of samples as a C++ program
# Suppose ./blockchain is a directory with files:
# latest-block.json transactions.json marketcap.json
quicktype ./blockchain -o blockchain-api.cpp

# quicktype a live JSON API as a Java program
quicktype https://api.somewhere.com/data -o Data.java
```

### Generating code from JSON schema

The recommended way to use `quicktype` is to generate a JSON schema from sample data, review and edit the schema, commit the schema to your project repo, then generate code from the schema as part of your build process:

```bash
# First, infer a JSON schema from a sample.
quicktype pokedex.json -l schema -o schema.json

# Review the schema, make changes,
# and commit it to your project repo.

# Finally, generate model code from schema in your
# build process for whatever languages you need:
quicktype -s schema schema.json -o src/ios/models.swift
quicktype -s schema schema.json -o src/android/Models.java
quicktype -s schema schema.json -o src/nodejs/Models.ts

# All of these models will serialize to and from the same
# JSON, so different programs in your stack can communicate
# seamlessly.
```

### Generating code from TypeScript (Experimental)

You can achieve a similar result by writing or generating a [TypeScript](http://www.typescriptlang.org/) file, then quicktyping it. TypeScript is a typed superset of JavaScript with simple, succinct syntax for defining types:

```typescript
interface Person {
name: string;
nickname?: string; // an optional property
luckyNumber: number;
}
```

You can use TypeScript just like JSON schema was used in the last example:

```bash
# First, infer a TypeScript file from a sample (or just write one!)
quicktype pokedex.json -o pokedex.ts --just-types
# Review the TypeScript, make changes, etc.
quicktype pokedex.ts -o src/ios/models.swift
```

### Calling `quicktype` from JavaScript

You can use `quicktype` as a JavaScript function within `node` or browsers. First add the `quicktype-core` package:

```bash
$ npm install quicktype-core
```

In general, first you create an `InputData` value with one or more JSON samples, JSON schemas, TypeScript sources, or other supported input types. Then you call `quicktype`, passing that `InputData` value and any options you want.

```javascript
import {
quicktype,
InputData,
jsonInputForTargetLanguage,
JSONSchemaInput,
FetchingJSONSchemaStore
} from "quicktype-core";

async function quicktypeJSON(targetLanguage, typeName, jsonString) {
const jsonInput = jsonInputForTargetLanguage(targetLanguage);

// We could add multiple samples for the same desired
// type, or many sources for other types. Here we're
// just making one type from one piece of sample JSON.
await jsonInput.addSource({
name: typeName,
samples: [jsonString]
});

const inputData = new InputData();
inputData.addInput(jsonInput);

return await quicktype({
inputData,
lang: targetLanguage
});
}

async function quicktypeJSONSchema(targetLanguage, typeName, jsonSchemaString) {
const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore());

// We could add multiple schemas for multiple types,
// but here we're just making one type from JSON schema.
await schemaInput.addSource({ name: typeName, schema: jsonSchemaString });

const inputData = new InputData();
inputData.addInput(schemaInput);

return await quicktype({
inputData,
lang: targetLanguage
});
}

async function main() {
const { lines: swiftPerson } = await quicktypeJSON("swift", "Person", jsonString);
console.log(swiftPerson.join("\n"));

const { lines: pythonPerson } = await quicktypeJSONSchema("python", "Person", jsonSchemaString);
console.log(pythonPerson.join("\n"));
}

main();
```

The argument to `quicktype` is a complex object with many optional properties. [Explore its definition](https://github.com/quicktype/quicktype/blob/master/packages/quicktype-core/src/Run.ts#L637) to understand what options are allowed.

## Contributing

`quicktype` is [Open Source](LICENSE) and we love contributors! In fact, we have a [list of issues](https://github.com/quicktype/quicktype/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Ahelp-wanted) that are low-priority for us, but for which we'd happily accept contributions. Support for new target languages is also strongly desired. If you'd like to contribute, need help with anything at all, or would just like to talk things over, come [join us on Slack](http://slack.quicktype.io/).

### Setup, Build, Run

`quicktype` is implemented in TypeScript and requires `nodejs` and `npm` to build and run.

First, install `typescript` globally via `npm`:

Clone this repo and do:

#### macOS / Linux

```bash
nvm use
npm install
script/quicktype # rebuild (slow) and run (fast)
```

#### Windows

```bash
npm install --ignore-scripts # Install dependencies
npm install -g typescript # Install typescript globally
tsc --project src/cli # Rebuild
node dist\cli\index.js # Run
```

### Edit

Install [Visual Studio Code](https://code.visualstudio.com/), open this
workspace, and install the recommended extensions:

```bash
code . # opens in VS Code
```

### Live-reloading for quick feedback

When working on an output language, you'll want to view generated
output as you edit. Use `npm start` to watch for changes and
recompile and rerun `quicktype` for live feedback. For example, if you're
developing a new renderer for `fortran`, you could use the following command to
rebuild and reinvoke `quicktype` as you implement your renderer:

```bash
npm start -- "--lang fortran pokedex.json"
```

The command in quotes is passed to `quicktype`, so you can render local `.json`
files, URLs, or add other options.

### Test

```bash
# Run full test suite
npm run test

# Test a specific language (see test/languages.ts)
FIXTURE=golang npm test

# Test a single sample or directory
FIXTURE=swift npm test -- pokedex.json
FIXTURE=swift npm test -- test/inputs/json/samples
```
Copyright 2025 Huajie Zhang
14 changes: 2 additions & 12 deletions packages/quicktype-core/src/input/JSONSchemaInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
mapMap,
mapMapSync,
mapMergeInto,
mapSortBy,
setFilter,
setSubtract
} from "collection-utils";
Expand Down Expand Up @@ -682,10 +681,9 @@ async function addTypesInSchema(
properties: StringMap,
requiredArray: string[],
additionalProperties: unknown,
sortKey: (k: string) => number | string = (k: string): string => k.toLowerCase()
): Promise<TypeRef> {
const required = new Set(requiredArray);
const propertiesMap = mapSortBy(mapFromObject(properties), (_, k) => sortKey(k));
const propertiesMap = mapFromObject(properties);
const props = await mapMapSync(propertiesMap, async (propSchema, propName) => {
const propLoc = loc.push("properties", propName);
const t = await toType(
Expand Down Expand Up @@ -908,15 +906,7 @@ async function addTypesInSchema(
inferredAttributes,
combineProducedAttributes(({ forObject }) => forObject)
);
const order = schema.quicktypePropertyOrder ? schema.quicktypePropertyOrder : [];
const orderKey = (propertyName: string): string => {
// use the index of the order array
const index = order.indexOf(propertyName);
// if no index then use the property name
return index !== -1 ? index : propertyName.toLowerCase();
};

return await makeObject(loc, objectAttributes, properties, required, additionalProperties, orderKey);
return await makeObject(loc, objectAttributes, properties, required, additionalProperties);
}

async function makeTypesFromCases(cases: unknown[], kind: string): Promise<TypeRef[]> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ export class JavaScriptRenderer extends ConvenienceRenderer {
if (!this._jsOptions.runtimeTypecheck) {
this.emitLine("return JSON.stringify(value);");
} else {
this.emitLine("return JSON.stringify(uncast(value, ", typeMap, "), null, 2);");
const spaceNum = this._jsOptions.jsonStringifySpaceNum;
this.emitLine("return JSON.stringify(uncast(value, ", typeMap, `), null, ${spaceNum});`);
}
} else {
if (!this._jsOptions.runtimeTypecheck) {
Expand Down
5 changes: 3 additions & 2 deletions packages/quicktype-core/src/language/JavaScript/language.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type RenderContext } from "../../Renderer";
import { BooleanOption, EnumOption, type Option, getOptionValues } from "../../RendererOptions";
import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions";
import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms";
import { convertersOption } from "../../support/Converters";
import { TargetLanguage } from "../../TargetLanguage";
Expand Down Expand Up @@ -28,7 +28,8 @@ export const javaScriptOptions = {
],
"json",
"secondary"
)
),
jsonStringifySpaceNum: new StringOption("json-stringify-space-size", "JSON.stringify space size", "4", "secondary"),
};

export class JavaScriptTargetLanguage extends TargetLanguage {
Expand Down