CV from JSON

Background

In an ideal world, a CV would serve as an as-close-to-real-time record of research output. In my experience, however,updates to my CV only are made when I required (often spurred by some deadline for a grant or application) or as a result of procrastination. Inevitably, different versions of a CV come to exist (e.g., the .PDF version that was sent as part of some application vs. the HTML version that sits, rather unchanging, on a rarely-visited website). More often than not, these versions end up being out-of-sync.

Using version control

A partial solution to the "multiple CVs" conundrum is to use version control, such as:

  • incremental copies with increasingly convoluted file names (e.g., CV_Dec_20_updated_Dec_21_final_final)
  • data stored and edited on the cloud (e.g., Google Drive or Dropbox)
  • use of a repository with sporadic, cryptically described commits

I say "partial solution" because what we1 are left with is a singular file that combines both contents and styling in one very specific way2. Transferring the CV into another format—say, as HTML—means that we now have multiple instances to edit every time we would like to make a change. Consequently, the likelihood that different formats may be out-of-sync with one another is nowhere near negligible. Case in point: in the past, the contents of my own CV page often have been slightly (and sometimes much more than slightly) different than the downloadable .PDF version available as a link on the same page.

JSON

If we would like our CVs to take different forms (or just want a better way to organize and update information), we must separate data from presentation. That way, the contents of a CV can be:

  1. stored in a non-proprietary, standard format
  2. easily version controlled
  3. adapted to different media and/or styles
  4. the same in every form of presentation that a CV may take (i.e., in a .PDF vs. on a website)

Since I have used JavaScript Object Notation (JSON) in previous projects, it is my data format of choice. JSON can be constructed in any text editor and comprises:

  1. name and value pairs (objects, which are wrapped in "{}")
  2. ordered list of values (arrays, which are wrapped in "[]")

By combining these two components, we can structure data so that it can be easily parsed and processed by both human beings and computer programs. For example, here is an excerpt from my cv.json file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
[
    {
		"type": "professional",
		"heading": "Professional Experience",
		"data": [
			{
				"date": "2019 -",
				"role": "Neukom Postdoctoral Fellow",
				"institution": "Dartmouth College",
				"location": "Hanover, NH"
			},
			{
				"date": "2011 - 2013",
				"role": "Researcher",
				"institution": "Situ Studio",
				"location": "Brooklyn, NY"
			}
		]
	}
]

This excerpt includes:

  1. an overarching object (enclosed by the brackets lines 1 and 20)
  2. an object containing the type, heading, and data associated with one section of my CV (in this case, Professional Experience; contained between the braces on lines 55 and 71)
  3. A "data" array (between the brackets on lines 57 and 70)
  4. One object for each professional role that I want to include in my CV, with date, role, institution, and location name and value pairs (lines 58 to 63 and lines 64 to 69)

You can view the entire cv.json file here.

Parsing the data

Clearly, storing your CV data in a single JSON file is a rather straightforward process. But how can you display this data in different formats?

Since JSON has broad recognition and support, it is relatively easy to parse your JSON file in the programming language of your choice (just search for "JSON" + "language" + "parser" and numerous libraries, some built in, will pop up). Parsing merely converts your text data into a format that the programming language understands and can interact with. Once the data have been parsed, you can format to your heart's content.

For example, in my case, I use the cv.json file to populate a LaTeX file (using LuaTeX) and the CV page on this website (using Hugo, which is my static site generator of choice).

Here is an excerpt from the LuaTeX file, where I load in the JSON file, parse it (line 9), and then build a table using the parsed data:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
\begin{luacode}
    -- My name (for citations)
    local myName = 'Mehra, A.'
    local myNameStylized = '\\textbf{Mehra, A.}'
    local f = io.open('cv.json', 'r')
    local s = f:read('*a')
    f:close()
    require("lualibs.lua")
    local data = utilities.json.tolua(s)
    tex.print('\\begin{center}') 
    tex.print('\\renewcommand{\\arraystretch}{1.5}')
    tex.print('\\begin{tabularx}{\\textwidth}{@{}D X@{}}')
    for dataKey, dataValue in ipairs(value["data"]) do
        local columnOne = dataValue["date"]
        if isEmpty(columnOne) then
            columnOne = ''
        end
        -- note, in some cases, you want column one not to be a date
        if value["type"] == "professionalActivities" then
            columnOne = dataValue["role"]
        end
        local thisContents
        if value["type"] == "education" then
            thisContents = '\\makecell[{{p{\\hsize}}}]{' .. dataValue["institution"] .. ', ' .. dataValue["location"] .. ' \\\\ ' .. dataValue["degree"] .. ' \\\\ Thesis: ' .. dataValue["thesis"] ..  ' \\\\ Advisor(s): ' .. dataValue["advisor"] .. '}'
            ...
        end
        if isEmpty(thisContents) then
            thisContents = ''
        end
        tex.print(columnOne .. ' & ' .. thisContents .. ' \\\\')
    end
    tex.print('\\end{tabularx}')
    tex.print('\\end{center}')
\end{luacode}

Here is another code excerpt showing parsing and formatting, this time to generate a webpage (written in go):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{{ $cv := getJSON "data/cv.json"}}
{{ range $cv }}
{{ $this_type := .type }}
    <div class="sixths_full six_column cv_element" id="{{ .type }}">
        <div class="sixths_full">
            <h3 class="cv_heading">{{ .heading }}</h3>
        </div>
        {{ range $index, $element := .data }}
            <div class="cv_date sixths_sixth start_left">
                ...
                {{ .date }}
            </div>
            <div class="sixths_two_thirds">
                ...
                {{ .description }}
            </div>
        {{ end }}
    </div>
{{ end }}

As both formats refer to the same data, updating my website and .PDF requires three simple steps:

  1. Make any changes
  2. Compile my latex file (using lualatex) and drop it into my local website directory
  3. Build (using hugo) and publish my website (by committing and pushing it to a repository)

Both the LaTeX and Hugo code that I wrote and use can be found here. Fair warning: my code is not streamlined and is very specific to my own CV. As such, it might best be used as a guide (though you are free to modify and copy as you please!).

[1] You are now a coconspirator, whether you want to be or not.

[2] Unless you opted for manually incremented copies in some local folder, because what you would be left with is a mess that can only bring sadness.