Skip to content

A powerful tool that automatically generates TypeScript interfaces from JSON objects, making type-safe development easier and more efficient.

Notifications You must be signed in to change notification settings

blacksmoke26/json2ts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

JSON to TypeScript Interface Converter

A powerful tool that automatically generates TypeScript interfaces from JSON objects, making type-safe development easier and more efficient.

Features ✨

  • πŸ”§ Convert JSON to TypeScript interfaces with ease
  • πŸ“¦ Generate separate interfaces for nested objects
  • πŸ”’ Intelligent type inference for Numbers, Strings, Booleans, and null values
  • πŸ“‹ Create type definitions for arrays, objects and primitive types
  • πŸ”„ Transform nested/complex JSON into flattened interface via --flat flag
  • ✏️ Specify custom names for root interfaces
  • πŸ—‚οΈ Preserve original JSON structure in generated interfaces
  • 🌐 Export options for generated interfaces (all, root, none)
  • πŸ“Š Handle complex nested structures with arrays of objects
  • πŸš€ Fast and lightweight CLI for quick conversions
  • πŸ“ Support for both file and direct text input
  • πŸ”Œ Read JSON output directly from the stdin for pipeline operations
  • ✏️ Added property name suggestion and correction logic based on strict TypeScript identifier rules
  • πŸ”„ Automatically detects and resolves circular references in JSON structures to prevent infinite recursion
  • πŸ›‘οΈ Generate strict TypeScript types with exact property matching when enabled via --strict flag
  • πŸ”’ Read-only Properties: Generate immutable interfaces with readonly modifier
  • ❓ Optional Properties: Generate interfaces with all properties marked optional (?)
  • πŸͺ Property Case Transformation: Convert property names to various case formats:
    • c - camelCase (userName)
    • l - lower_snake_case (user_name)
    • o - preserve original (default)
    • p - PascalCase (UserName)
    • u - UPPER_SNAKE_CASE (USER_NAME)
    • k - kebab-case (user-name)
  • πŸ“ Smart Array Type Detection: Automatically infers array types including:
    • Primitive arrays (e.g., string[], number[])
    • Mixed-type tuples (e.g., [string, number, boolean])
    • Object arrays (e.g., User[])
    • Nested arrays with proper type preservation
  • πŸ—ΊοΈ Custom Type Mapping: Override default type detection with custom mappings:
    • Map specific JSON properties to custom TypeScript types
    • Useful for integrating with existing type definitions
    • Example: Map "user_id" to UserID type
    • Configure via typeMap option in API or CLI

Command Line Interface πŸ’»

The package includes a command-line interface (CLI) for quick conversions without writing code.

Installation πŸ“¦

npm install -g @junaidatari/json2ts   # NPM
pnpm install -g @junaidatari/json2ts  # PNPM
yarn global add @junaidatari/json2ts  # Yarn

Command Options βš™οΈ

Option Type Description Default
-f, --file string Path to JSON file to convert Required*
-t, --text string Raw JSON string to convert Required*
-o, --output string Output file path Prints to console
-n, --name string Root interface name RootObject
-l, --flat boolean Generate flattened interface -
-e, --export string Export type: a=all, r=root, n=none r (root)
--pc, --property-case string Property case transformation: c=camelCase, l=lower_snake, o=original, p=PascalCase, u=UPPER_SNAKE, k=kebab-case o (original)
-s, --strict boolean Generate strict TypeScript types with exact property matching -
-r, --readonly boolean Make all generated properties readonly -
--op, --optional boolean Make all generated properties optional -

Either --file or --text must be provided or pipe through to read directly from the stdin.

Examples πŸ“

Basic file conversion

json2ts -f input.json -o types.ts -n ApiResponse

Direct text conversion

# Linux/Mac
json2ts -t '{"user": {"name": "John"}}' -n User

# Windows
json2ts -t "{\"user\": {\"name\": \"John\"}}" -n User

Readonly properties

# Generate with readonly properties
json2ts -f input.json -o readonly-types.ts -n Data --readonly

# Combine with strict mode
json2ts -f input.json -o strict-readonly.ts -n Data --strict --readonly

Optional properties

# Generate with optional properties
json2ts -f input.json -o optional-types.ts -n Data --op

# Combine with readonly mode
json2ts -f input.json -o readonly-optional.ts -n Data --readonly --optional

Generate flattened interface

json2ts -f complex.json -o flat-types.ts -n Data --flat

Export all interfaces

json2ts -f input.json -o types.ts -n Response -e a

No exports (internal interfaces)

json2ts -f input.json -o types.ts -n Response --export n

Property case transformation

# Convert to camelCase properties
json2ts -f input.json -o camel-types.ts --pc c

# Convert to PascalCase properties
json2ts -f input.json -o pascal-types.ts --property-case p

# Convert to kebab-case properties
json2ts -f input.json -o kebab-types.ts --property-case k

Strict mode generation

# Generate with strict type checking
json2ts -f input.json -o strict-types.ts -n Data --strict

Combined options

# Multiple options together
json2ts -f input.json -o output.ts -n ApiResponse -e a --property-case c --strict

# Flattened with property transformation
json2ts -f data.json -o flat.ts -n FlatData --flat --property-case l

Root-only export

# Export only root interface (default)
json2ts -f input.json -o types.ts -n Response
# or explicitly
json2ts -f input.json -o types.ts -n Response -e r

Pipeline with curl

curl -s https://jsonplaceholder.typicode.com/posts/1 | \
  json2ts -n UserResponse -o user-types.ts

Pipeline with other commands

# Convert from clipboard (Linux)
xclip -selection clipboard -o | json2ts -n ClipboardData

# Convert from file and copy to clipboard
json2ts -f data.json | tee types.ts | pbcopy

# Format with prettier
curl -s https://api.example.com/data | json2ts -n Data | \
  npx prettier --parser typescript

Configuration files

# Convert package.json
cat package.json | json2ts -n PackageConfig -o package-types.ts

# Convert tsconfig.json
json2ts -f tsconfig.json -n TsConfig -o tsconfig-types.ts

Database exports

# MongoDB export
mongoexport --collection users --out users.json
json2ts -f users.json -n UserDoc -o user-types.ts --export a

# PostgreSQL query
psql -c "SELECT row_to_json(t) FROM (SELECT * FROM users) t" | \
  json2ts -n DBUser -o db-types.ts

Interactive usage

echo '{"name": "test", "data": {"items": [1, 2, 3]}}' | \
  json2ts -n TestData

json2ts -n Config -o config-types.ts << EOF
{
  "server": {"port": 3000},
  "database": {"url": "mongodb://localhost"}
}
EOF

Development workflows

# Generate types from API schema
curl -s "$API_SCHEMA_URL" | json2ts -n Schema -o src/types/api.ts

# Watch for changes
while inotifywait -e modify data/; do
  for file in data/*.json; do
    base=$(basename "$file" .json)
    json2ts -f "$file" -o "types/${base}.ts" -n "${base^}Type"
  done
done

# Process all JSON files
find src/data -name "*.json" -exec sh -c \
  'json2ts -f "$0" -o "src/types/$(basename "$0" .json).ts"' {} \;

Multiple files script

for file in data/*.json; do
  base=$(basename "$file" .json)
  json2ts -f "$file" -o "types/${base}.ts" -n "${base^}Data"
done

Real-world API integration

# GitHub API: Get repository information
curl -s https://api.github.com/repos/torvalds/linux | \
  json2ts -n GithubRepo -o repo-types.ts --property-case c

# Reddit API: Fetch subreddit posts
curl -s -H "User-Agent: json2ts" \
  "https://www.reddit.com/r/typescript/top.json?limit=10" | \
  json2ts -n RedditPost -o reddit-types.ts --export a

# GraphQL API query with curl
curl -s -X POST https://api.spacex.land/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "{ launches { id name rocket { name } } }"}' | \
  jq -r '.data.launches[0]' | \
  json2ts -n SpaceXLaunch -o spacex-types.ts --property-case p

Database schema introspection

# PostgreSQL schema extraction
psql -d myapp -c "
  SELECT json_agg(t) FROM (
    SELECT 
      table_name,
      array_agg(column_name::text) as columns,
      array_agg(data_type::text) as types
    FROM information_schema.columns 
    WHERE table_schema = 'public'
    GROUP BY table_name
  ) t
" | json2ts -n DBSchema -o db-schema.ts --readonly

# MongoDB collection structure analysis
mongo myapp --eval "
  db.users.findOne().forEach(printjson)
" | json2ts -n MongoUser -o mongo-types.ts --strict

# Prisma schema introspection
npx prisma introspect --print | \
  grep -o '"model"[^}]*}' | \
  json2ts -n PrismaModel -o prisma-types.ts --export a

Configuration management

# Kubernetes deployment analysis
kubectl get deployment myapp -o json | \
  json2ts -n K8sDeployment -o k8s-types.ts --readonly

# Docker compose configuration
docker compose config --format json | \
  json2ts -n DockerCompose -o compose-types.ts --property-case l

# Terraform state parsing
terraform show -json | \
  jq '.values.root_module.resources[] | select(.type == "aws_instance")' | \
  json2ts -n TFInstance -o terraform-types.ts --strict

Testing and validation

# Generate test types from JSON schema
jsonschema2jsonpointer schema.json | \
  jq -r '.[] | .pointer' | \
  xargs -I {} json2ts -f schema.json -n TestSchema --strict

# Validate API responses against types
for endpoint in users posts comments; do
  curl -s "https://api.example.com/$endpoint" | \
    json2ts -n "${endpoint^}Response" -o "test/types/${endpoint}.ts"
done

# Generate mock data types
jq -n '{
  users: [range(10) | {
    id: .,
    name: "User\(.)",
    email: "user\(.)@example.com",
    roles: ["user", (\. % 3 == 0 and "admin" or empty)]
  }]
}' | json2ts -n MockUsers -o mock-types.ts --export a

Advanced pipeline operations

# Multi-stage transformation
curl -s https://api.exchangerate-api.com/v4/latest/USD | \
  jq '{rates: .rates | to_entries | map({key: .key, value: .value})}' | \
  json2ts -n ExchangeRate -o rates.ts --property-case c | \
  npx prettier --parser typescript > src/types/rates.ts

# Parallel processing
echo 'users posts comments products' | \
  tr ' ' '\n' | \
  xargs -P 4 -I {} bash -c "
    curl -s \"https://api.example.com/{}\" | \
      json2ts -n \"\$(echo {} | sed 's/.*/\u&/')\" -o \"types/{}.ts\"
  "

# Conditional type generation
json2ts -f data.json -o temp.ts -n Data && \
if grep -q 'interface.*{' temp.ts; then
  echo "Generated interface:"
  cat temp.ts
else
  echo "No interfaces generated"
fi
rm temp.ts

Enterprise workflows

# Service mesh configuration
istioctl proxy-config routes deployment/reviews.default -o json | \
  jq '.httpRoutes[0].route[0].match' | \
  json2ts -n IstioRoute -o istio-types.ts --readonly

# OpenAPI schema conversion
curl -s https://petstore.swagger.io/v2/swagger.json | \
  jq '.definitions' | \
  json2ts -n PetStore -o api-types.ts --export a

# Microservice contract generation
for service in auth payment notification; do
  curl -s "https://contract-registry.internal/api/v1/contracts/$service" | \
    jq '.schema' | \
    json2ts -n "${service^}Contract" -o "src/contracts/${service}.ts" --strict
done

# CloudFormation template parsing
aws cloudformation get-template --stack-name my-stack | \
  jq -r '.TemplateBody' | \
  json2ts -n CFTemplate -o cf-types.ts --property-case k

CI/CD integration

# GitHub Actions workflow validation
find .github/workflows -name '*.yml' -exec \
  yq eval -o json {} \; | \
  json2ts -n GitHubAction -o action-types.ts

# Azure DevOps pipeline analysis
az pipelines show --id $(az pipelines list --query [0].id -o tsv) | \
  jq '.process' | \
  json2ts -n AzPipeline -o pipeline-types.ts

# Dockerfile instruction parsing
docker inspect $(docker build -q .) | \
  jq -r '.[0].Config.Labels' | \
  json2ts -n DockerLabels -o labels.ts --readonly

Tips πŸ’‘

  • Check version: json2ts --version
  • View help: json2ts --help

Programmatic API πŸ“š

Installation

npm install @junaidatari/json2ts   # NPM
pnpm install @junaidatari/json2ts  # PNPM
yarn add @junaidatari/json2ts      # Yarn

Usage πŸš€

import { 
  JsonToTsConverter, 
  JsonToFlattenedTsConverter, 
} from '@junaidatari/json2ts';

// Sample JSON object
const json = {
  user: {
    name: 'John',
    age: 30,
    address: {
      street: '123 Main St',
      city: 'New York'
    }
  }
};

// Sample JSON string
const jsonText = `{
  "_id": "691da8feb00505c1c11b08b9",
  "index": 0,
  "guid": "9150daa4-b7c4-4230-a3b8-ddd2eb05731f",
  "isActive": true,
  "balance": "$3,816.81",
  "picture": "http://placehold.it/32x32",
  "age": 39,
  "eyeColor": "blue",
  "name": "Vickie Snow",
  "gender": "female",
  "company": "DATACATOR",
  "email": "vickiesnow@datacator.com",
  "phone": "+1 (925) 537-2747",
  "address": "843 Interborough Parkway, Floris, Washington, 5608",
  "registered": "2018-11-01T06:02:48 -05:00",
  "latitude": -42.568798,
  "longitude": -77.971543,
  "tags": [
    "fugiat",
    "reprehenderit",
    "culpa",
    "veniam",
    "enim",
    "occaecat",
    "et"
  ],
  "friends": [
    {
      "id": 0,
      "name": "Silvia Ferrell"
    },
    {
      "id": 1,
      "name": "Kirkland Benson"
    },
    {
      "id": 2,
      "name": "Howe Hester"
    }
  ],
  "greeting": "Hello, Vickie Snow! You have 10 unread messages.",
  "favoriteFruit": "strawberry"
}
`;

// Convert to multiple interfaces with all exports
const interfaces = JsonToTsConverter.convert(json, 'Person', 'all');
console.log('Generated interfaces:');
console.log(interfaces);
/* Output:
export interface Person {
  user: User;
}

export interface User {
  name: string;
  age: number;
  address: Address;
}

export interface Address {
  street: string;
  city: string;
}
*/

// Convert to flattened interface
const interfaceFlat = JsonToFlattenedTsConverter.convert(jsonText, 'PersonFlat', 'all');
console.log('\nGenerated flattened interface:');
console.log(interfaceFlat);
/* Output:
export interface PersonFlat {
  _id: string;
  index: number;
  guid: string;
  isActive: boolean;
  balance: string;
  picture: string;
  age: number;
  eyeColor: string;
  name: string;
  gender: string;
  company: string;
  email: string;
  phone: string;
  address: string;
  registered: string;
  latitude: number;
  longitude: number;
  tags: string[];
  friends: {
    id: number;
    name: string;
  }[];
  greeting: string;
  favoriteFruit: string;
}
*/

// Example with complex nested structure
const complexJson = {
  data: {
    users: [
      {
        id: 1,
        profile: {
          name: 'Alice',
          preferences: {
            theme: 'dark',
            notifications: {
              email: true,
              push: false
            }
          }
        }
      }
    ],
    metadata: {
      total: 1,
      page: 1
    }
  }
};

const complexTypes = JsonToTsConverter.convert(complexJson, 'ApiResponse', 'root');
console.log(complexTypes);
/* Output:
export interface ApiResponse {
  data: Data;
}

interface Data {
  users: User[];
  metadata: Metadata;
}

interface User {
  id: number;
  profile: Profile;
}

interface Profile {
  name: string;
  preferences: Preferences;
}

interface Preferences {
  theme: string;
  notifications: Notifications;
}

interface Notifications {
  email: boolean;
  push: boolean;
}

interface Metadata {
  total: number;
  page: number;
}
*/

// Real-world example: API response handler
async function handleApiResponse() {
  // Simulate API response
  const apiResponse = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  const data = await apiResponse.json();

  // Generate types dynamically
  const types = JsonToTsConverter.convert(data, 'PostResponse', 'root');
  console.log(types);
  /*
  export interface PostResponse {
    userId: number;
    id: number;
    title: string;
    body: string;
  }
  */
}

API Reference πŸ“–

Methods

JsonToTsConverter.convert(json, name?, export?, options?)

JsonToFlattenedTsConverter.convert(json, name?, export?, options?)

Converts JSON to TypeScript interfaces.

Parameters:

  • json: JSON object or string to convert
  • name: Root interface name (default: 'RootObject')
  • export: Export mode ('all', 'root', 'none') (default: 'root')
  • options: Configuration options for conversion (optional)
    • arrayMaxTupleSize: Maximum number of items to convert to tuple type (default: 10)
    • arrayMinTupleSize: Minimum number of items required to create a tuple type (default: 2)
    • strict: Enable strict type checking for better type inference (default: false)
    • typeMap: Custom type mapping for specific JSON structures (default: {})
    • propertyCase: Naming convention for generated property names (default: 'original')
    • readonlyProperties: Make all generated properties readonly (default: false)
    • optionalProperties: Make all generated properties optional (default: false)

Returns: Generated TypeScript interfaces string

Contributing 🀝

We welcome contributions! Please follow these steps:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Setup πŸ”§

git clone https://github.com/blacksmoke26/json2ts.git
cd json2ts
npm install
npm run dev
npm run dev:flat

Testing CLI with /samples/*.json JSON files

npm run build
node .\bin\json2ts -f .\samples\jsons\sample.json -n Sample1
node .\bin\json2ts -f .\samples\jsons\sample2.json -n Sample2 -o sample2.ts --flat

Running test cases

npm run test

License πŸ“„

This project is licensed under the ISC License.

Support πŸ’¬

If you encounter issues or have questions:

Acknowledgments πŸ™

  • Originally developed for Posquelize
  • Thanks to all contributors
  • Inspired by the need for type safety in JSON-heavy applications

Copyright ©️

Developed with ❀️ by Junaid Atari