ResumeJSON

JSON Resume schema: a complete example, and how to fill it from a CV

A JSON Resume example is a JSON document with a fixed set of top-level sections — basics, work, volunteer, education, awards, certificates, publications, skills, languages, interests, references and projects — and nothing else is required. Below is a complete worked example of the whole document, then the part the standard's own pages leave open: how to get an existing PDF or DOCX CV into that shape. That last step is a mapping job, and this article does it concretely, including the field-by-field table from the output of a parsing API to the schema's field names.

One thing to say first, because this article is written by a vendor: ResumeJSON is a paid resume parsing API, and its output is its own schema, not JSON Resume's. If you want the exact JSON Resume shape you are mapping one object to another — a short, mechanical step, shown in full below. Every claim here about JSON Resume was read from jsonresume.org in September 2026, and the schema is theirs to change — the list of sections, the example below and the absence of any importer are all as of September 2026.

What the JSON Resume schema covers

JSON Resume describes itself as "a community driven open-source initiative to create JSON-based standard for resumes", released under the MIT license, with the schema on GitHub and a CLI, a registry and a gallery of community themes around it. The document is deliberately flat: one object, a fixed list of keys, arrays where a person can have several of something.

SectionWhat goes in itWhere a CV states it
basicsName, label, email, phone, URL, summary, location, and profiles[] for GitHub, LinkedIn and similarThe header of the CV
work[]Employer name, position, url, startDate, endDate, summary, highlights[]The experience section
volunteer[]Same shape as work, for unpaid rolesUsually a separate section, often omitted
education[]institution, area, studyType, dates, score, courses[]The education section
skills[]Objects with name, level and keywords[]A skills list or the text of the roles
languages[]language and fluencySometimes a sidebar, sometimes nowhere
projects[]name, description, highlights[], keywords[], roles[], datesA portfolio section, or a GitHub profile
awards[], certificates[], publications[]One object each, with dates and an issuer or publisherSeparate sections, and the most often missing
interests[], references[]Names and keywords; reference lettersAlmost never on a modern CV

Two details matter more than the table suggests. Dates are free text in practice — the schema's own example shows "2013-01-01", but nothing enforces it, and a CV says "March 2022" or "2019 – Present", so normalising dates is work you own. And every section is optional: a valid JSON Resume can carry basics and one work entry, which is why the format is popular with tooling that would rather render nothing than crash.

A complete JSON Resume example

This is the whole document, written the way a filled-in one looks after a real CV has been mapped into it. It is abridged only in the number of entries per array.

{
  "basics": {
    "name": "John Doe",
    "label": "Programmer",
    "image": "",
    "email": "john@gmail.com",
    "phone": "(912) 555-4321",
    "url": "https://johndoe.com",
    "summary": "Backend engineer, eight years, mostly payments.",
    "location": {
      "address": "2712 Broadway St",
      "postalCode": "CA 94115",
      "city": "San Francisco",
      "countryCode": "US",
      "region": "California"
    },
    "profiles": [
      { "network": "Twitter", "username": "john", "url": "https://twitter.com/john" }
    ]
  },
  "work": [
    {
      "name": "Company",
      "position": "President",
      "url": "https://company.com",
      "startDate": "2013-01-01",
      "endDate": "2014-01-01",
      "summary": "Description…",
      "highlights": ["Started the company"],
      "location": "San Francisco, CA"
    }
  ],
  "education": [
    {
      "institution": "University",
      "url": "https://institution.com/",
      "area": "Software Engineering",
      "studyType": "Bachelor",
      "startDate": "2011-01-01",
      "endDate": "2013-01-01",
      "score": "4.0",
      "courses": ["DB1101 - Basic SQL"]
    }
  ],
  "skills": [
    { "name": "Web Development", "level": "Master", "keywords": ["HTML", "CSS", "JavaScript"] }
  ],
  "languages": [{ "language": "English", "fluency": "Native speaker" }],
  "projects": [
    {
      "name": "Project",
      "description": "Description…",
      "highlights": ["Won award at AIHacks 2016"],
      "keywords": ["Time Tracking"],
      "startDate": "2019-01-01",
      "endDate": "2021-01-01",
      "url": "https://project.com/",
      "roles": ["Team Lead"],
      "entity": "Entity",
      "type": "application"
    }
  ]
}

work[] entries carry a name for the employer, not the person — the field is named for the company, which reads oddly the first time. basics.profiles[] is where GitHub, LinkedIn and personal sites go; there is no dedicated field for any of them.

Three ways to fill a JSON Resume from a CV

The standard ships no importer. jsonresume.org's own navigation is Home, Getting Started, CLI Tools, Schema, Themes, Projects, Hosting — there is no "upload a PDF" anywhere in it, so whoever fills the JSON is you. In practice there are three routes, and they differ mostly by how much of the CV you retype.

RouteWhat you writeHonest verdict
Type it by handThe JSON, in the CLI or the registry editorCheapest for one CV, unthinkable at fifty
Open-source extractor, then mapExtraction code plus your own field mappingGood if CVs cannot leave your infrastructure, or parsing is not the point
Parsing API, then mapA parse call plus a field mappingThe mapping is the same work; the extraction is not

Typing it by hand is genuinely fine and worth saying so. The JSON Resume CLI and the hosted registry exist for exactly this, and if you maintain one resume, a JSON file you edit twice a year beats a pipeline. It stops being fine when a form uploads a CV and someone has to retype it before the application can be scored.

An open-source extractor plus a mapping keeps everything on your own machines, which is the deciding factor if CVs cannot leave your infrastructure. The extraction half is solved — open source resume parser walks through what each project actually gives you, including where it stops. What that route costs you is the field decisions: turning a layout-preserving text rendering into a position and a startDate, and doing it again when your corpus shifts.

A parsing API plus a mapping moves the field decisions to somebody else and leaves you the mapping, which is a table lookup — the one below. The trade is a network call and a subscription instead of a corpus you maintain.

"JSON Resume is a community driven open-source initiative to create JSON-based standard for resumes." — jsonresume.org, read September 2026

Mapping a parsed resume into the schema

This is the whole mapping, from ResumeJSON's response object to JSON Resume's field names. Nothing else is needed: the output is typed, dates are already YYYY-MM or YYYY, and a field the CV does not state comes back null rather than guessed.

JSON ResumeResumeJSON outputNote
basics.namebasics.full_name
basics.labelbasics.headlineThe CV's own wording, not a title you assign
basics.email, basics.phonebasics.email, basics.phone
basics.location.addressbasics.locationOne string, so the parts stay joined
basics.profiles[].urlbasics.links[]URLs only; the network is not classified
basics.summaryNot extracted: a summary is prose you write
work[].namework[].company
work[].positionwork[].title
work[].startDate, endDatework[].start_date, end_dateAlready normalised; end_date is null while a role is current, and work[].is_current carries that explicitly
work[].highlights[]work[].highlights[]Bullet lines kept as an array
education[].institutioneducation[].institution
education[].studyType, areaeducation[].degree, field_of_study
skills[].keywords[]skills[]An array of strings, so it maps onto keywords and leaves name and level to you
languages[].language, fluencylanguages[].language, proficiency
certificates[]certifications[]name, issuer and a YYYY-MM or YYYY date
total_years_experienceNo JSON Resume field; computed from the roles, with overlapping roles counted once

Two honest gaps. The schema has no place for a computed total, so total_years_experience is yours to use or drop. And basics.summary, skills[].level and the whole awards, publications and references families are not in a parse response — a parser reads what the document says, and levels or reference letters are usually not in it.

Who should not use a parsing API

The mapping above is small, so the reason to pick a route is not the mapping — it is where the extraction should live.

Everyone else — a job board, an ATS, a matching tool taking uploads from strangers — is choosing between maintaining field decisions or buying them, and the JSON Resume mapping is the same short table either way.

If you want to see the output shape before committing to any of this, the free parser returns the same JSON the paid endpoint does, and the field reference documents every key.

All articles