GithubHelp home page GithubHelp logo

glideapps / quicktype Goto Github PK

View Code? Open in Web Editor NEW
11.5K 90.0 1.0K 18.8 MB

Generate types and converters from JSON, Schema, and GraphQL

Home Page: https://app.quicktype.io

License: Apache License 2.0

Shell 0.22% Python 0.56% TypeScript 97.55% JavaScript 1.66% PowerShell 0.01%
json typescript json-schema elm java swift graphql csharp cplusplus golang

quicktype's Introduction

npm version Build status

quicktype generates strongly-typed models and serializers from JSON, JSON Schema, TypeScript, and GraphQL queries, making it a breeze to work with JSON type-safely in many programming languages.

Supported Inputs

JSON JSON API URLs JSON Schema
TypeScript GraphQL queries

Target Languages

Ruby JavaScript Flow Rust Kotlin
Dart Python C# Go C++
Java Scala TypeScript Swift Objective-C Elm
JSON Schema Pike Prop-Types Haskell PHP

Missing your favorite language? Please implement it!

Installation

There are many ways to use quicktype. 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:

npm install -g quicktype

Using quicktype

# 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:

# 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 file, then quicktyping it. TypeScript is a typed superset of JavaScript with simple, succinct syntax for defining types:

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:

# 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:

$ 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.

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 to understand what options are allowed.

Contributing

quicktype is Open Source and we love contributors! In fact, we have a list of issues 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.

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

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

Windows

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, open this workspace, and install the recommended extensions:

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:

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

# 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

quicktype's People

Contributors

about-code avatar agisboye avatar algas avatar asarazan avatar bitsol avatar davidhodge avatar deepsource-autofix[bot] avatar dependabot[bot] avatar dvdsgl avatar ender-events avatar gifanonim avatar harsszegi avatar inferrinizzard avatar krk avatar mamantoha avatar mkrawczuk avatar mrrooni avatar murnto avatar ozum avatar remorses avatar riih avatar rmondjone avatar schani avatar skornel02 avatar thatsokay avatar thegoldenmule avatar uhop avatar untitaker avatar waywardmonkeys avatar wgottschalk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quicktype's Issues

Allow non-inferred class names

Right now all class names are inferred from property names via regatherClassNames. That's fine for JSON input, where classes are not named. In JSON Schema it is possible to name classes, so wherever we have a class name we should preserve it, and not try re-infer it. This should be easy to do by making the names property of IRClassData an Either String (Set String) instead of just a Set String.

Handle toplevel better

fromJson should ideally be in the top-level class. Figure out how to handle these three cases:

  1. There is one class that can be interpreted as top level.
  2. There is no class at all.
  3. There is more than one class that can be interpreted as top level.

Exposing the Converter class is not ideal because it inherits from JsonConverter, which serves a different purpose than what we want to expose.

Add more tests

In particular, all the smaller ones from the Awesome JSON dataset.

Enforce required fields in Go

This code via Gustavo Poscidonio from Slack. We could use this to do arbitrary validation.

package main

import (
	"encoding/json"
	"fmt"
)

type Pokemon struct {
	Name     string   // required
	Type     []string // required with length >= 1
	Nickname string   // not required
}

func (p *Pokemon) UnmarshalJSON(data []byte) error {
	var aux struct {
		Name     string
		Type     []string
		Nickname string
	}

	err := json.Unmarshal(data, &aux)
	if err != nil {
		return err
	}

	if aux.Name == "" {
		return fmt.Errorf("Name field not set for Pokemon")
	}

	if len(aux.Type) < 1 {
		return fmt.Errorf("Type field not set for Pokemon")
	}
	
	p.Name = aux.Name
	p.Type = aux.Type
	p.Nickname = aux.Nickname

	return nil
}

var validPokemon = []byte(`
{
	"name" : "Bulbasaur",
	"type" : ["grass", "poison"],
	"nickname" : "little foot"
}
`)

var invalidPokemon = []byte(`
{
	"name" : "Bulbasaur",
	"nickname" : "little foot"
}
`)

func main() {
	var pokemon Pokemon
	fmt.Println(json.Unmarshal(invalidPokemon, &pokemon))
	fmt.Println(json.Unmarshal(validPokemon, &pokemon))
	fmt.Printf("My pokemon: %+v\n", pokemon)
}

Subclasses in the IR?

Extending the similarity metric to include subclasses as similar led to some mayhem, but if we had proper subclasses in the IR that could be avoided. For example, in github-events.json, there's a small repo and a large repo class, the large one containing a strict superset of the small one. The large one could be a proper subclass of the smaller one.

Better map heuristics

Heuristics:

  • Same property types
  • Large number of properties
  • Property names that don't look like names
  • Detect specific patterns in names, like hashes or numbers

Make Elm output nicer

  • Remove comments
  • Omit unnecessary parentheses
  • Use toplevel name for Root
  • Add explanatory comments
  • All type definitions before encoders and decoders
  • Move toplevel definition up
  • Expose all types
  • No more underscores in names
  • Array and Dict instead of Array.Array and Dict.Dict

Launch blog post

Once we add options, we should blog about them and also mention:

  • Name combination
  • Class de-duplication
  • Map detection
  • Optional types rather than default values (e.g. null : int? not 0 : int)
  • Numeric types

Command line client

If only for the use case of running with large JSON files.

Generate go to parse latest Bitcoin block

$ quicktype -o latest-block.go \
  "https://blockchain.info/rawblock/0000000000000bae09a7a393a8acded75aa67e46cb81f7acaa5ad94f9eacd103"

Support enums

For string properties, can we form a relatively small set of equivalence classes from a large number of samples? We might represent that as an enum (if the target language has enums).

There are two parts to this:

  • Supporting enums in our IR, accepting them from JSON Schema, and producing code for them
  • Automatically detecting them from given JSON samples

We can and should do the former, whether we ever do the latter or not.

Sort classes

I think the classes should be sorted by a breadth-first traversal of the graph, starting from the top-level type. At the same depth we could sort alphanumerically, for example.

More sound similar class detector

Right now we pick one class and then find all classes that are similar to it. But depending on which class you start out with, you can end up with different sets. So we might want to find sets where all classes are pairwise similar. The complexity of that is most likely larger, definitely when implemented naively.

Command line package

$ # Generate go to parse latest Bitcoin block
$ quicktype -o latest-block.go \
  "https://blockchain.info/rawblock/0000000000000bae09a7a393a8acded75aa67e46cb81f7acaa5ad94f9eacd103"

Option to parse missing arrays as empty rather than null

In this example, one person has no friends property, so this may result in a null array property in C#. We should consider an option to parse missing arrays as empty rather than null.

{
    "people": [
        {
            "name": "Nice Bob",
            "friends": ["David"]
        },
        {
            "name": "Evil Bob"
        }
    ]
}
public class Person
{
	[JsonProperty("friends")]
	public string[] Friends { get; set; }

	[JsonProperty("name")]
	public string Name { get; set; }

}

Use incremental parsing

We can't keep the whole JSON document in memory. I get heap overflows with the default V8 settings for JSON files as small as 250ish MB.

Make Go output fmt-compliant

  • JSON attributes are not horizontally aligned:
 type TopLevel struct {
-	Y []*float64 `json:"y"` // array of optional
-	X []DoubleOrNullOrString `json:"x"`
+	Y []*float64               `json:"y"`
+	X []DoubleOrNullOrString   `json:"x"`
 	Z []DoubleOrDoubleArrayOrZ `json:"z"`
 }

And weirdly it deletes comments. That must be a bug.

  • Align comments (on consecutively commented lines)
  • Use tab for indentation
  • Don't pad last table column

Fix IRAnything

IRAnything currently serves two purposes in the IR:

  1. In inference, to signify a type we know nothing about. The only way for it to come about is as the element type of an empty array.

  2. In generation, for any type, which we translate to object in C#.

We make no explicit distinction between the two in the code, i.e. they are one and the same.

That mostly works for now, but we will run into trouble if our inference algorithm ever wants to distinguish between the two. In addition to that, JSON Schema does have a representation for "any type", but our unification algorithm does not treat IRAnything as "any type", so we can't use and expect to get correct results. For example, if we treat "any type" as IRAnything, we would unify an array that contains one "any type" and one integer as an array containing integers. The correct unification is an array containing "any type".

If we had IRNoInformation and IRAny, unification would look like this:

unify IRNoInformation x = x
unify IRAny x = IRAny

Of course, to preserve more type information we could still do

unify IRAny x = IRUnion [IRAny, x]

Support tuples

In the simplest case, an array of arrays, or dictionary of arrays, where each inner array has the same structure (same length, same element types), can be interpreted as an array of tuples, or dictionary of tuples. Eg.

[[1, true, "abc"],
 [2, false, "foo"],
 [3, true, "bar"]]

would be an Array (Tuple [Int, Bool, String])

Customization

For the backends we can start with boolean options, for all languages we'd like the ability to at least give a top level class name.

We can later expand this to typed options. It seems that generics can be used for this.

Handle toplevel properly

  • TopLevel class should come first
  • don't test for class name TopLevel
  • Handle non-class JSON (we don't even generate a TopLevel class for that now)

Support dates

{
    "DepartureDateTime": "2016-08-13T18:15:00",
    "ArrivalDateTime": "2016-08-13T19:27:00"
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.