<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Greg Clark</title>
    <description>The latest articles on DEV Community by Greg Clark (@clarkgrg).</description>
    <link>https://dev.to/clarkgrg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F516115%2F3b265308-c439-4509-bf17-55ae6a50ecb8.jpeg</url>
      <title>DEV Community: Greg Clark</title>
      <link>https://dev.to/clarkgrg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/clarkgrg"/>
    <language>en</language>
    <item>
      <title>3 TIL writing a JSON Parser in Typescript</title>
      <dc:creator>Greg Clark</dc:creator>
      <pubDate>Mon, 23 Nov 2020 14:25:34 +0000</pubDate>
      <link>https://dev.to/clarkgrg/3-til-writing-a-json-parser-in-typescript-25mk</link>
      <guid>https://dev.to/clarkgrg/3-til-writing-a-json-parser-in-typescript-25mk</guid>
      <description>&lt;p&gt;I decided one afternoon to write a JSON parser to improve my Typescript skills and reinforce what I learned from Ruslan Spivak's excellent blog series &lt;a href="https://ruslanspivak.com/lsbasi-part1/"&gt;Let's Build a Simple Interpreter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I used the &lt;a href="https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf"&gt;JSON Interchange Standard - 2nd addition&lt;/a&gt; as a reference for the implementation  &lt;/p&gt;

&lt;p&gt;The JSON Parser has 3 main components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a Lexer to tokenize the JSON string &lt;/li&gt;
&lt;li&gt;a Parser to interpret the JSON grammer, and &lt;/li&gt;
&lt;li&gt;a JSONBuilder to create the Javascript representation of the JSON.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Here is what I learned&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. I write better and faster code with Typescript.
&lt;/h3&gt;

&lt;p&gt;I wrote each of the 3 main components in turn, the Lexer, Parser, and JSON builder.  Nearly 600 lines of code in total in one afternoon.  I'd write maybe 200 lines at a time then test it out.  Not once did I receive compile time errors.  I was truly shocked, fully expecting some error.  I only had logic errors in my code.  I was literally expecting to see a misnamed variable or some other error but I didn't see any complaints.  All of these issues were caught in the editor while I was typing.  This allowed me to fix 'would-be' errors on the fly as I was creating the program.  &lt;strong&gt;Typescript just makes better code right out of the gate.&lt;/strong&gt;  Since I didn't have these compile time errors to find and fix Typescript allowed me to move faster than I would if I would have used Javascript alone.  &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Its easy to allow Javascript to use your Typescript npm packages but you have to plan for it.
&lt;/h3&gt;

&lt;p&gt;After getting my parser completed, I was excited to publish to npm.  This is the first package I ever published to npm.  To test it out I created a parse-test project on my local machine and installed &lt;code&gt;ts-jsonparse&lt;/code&gt;.  &lt;strong&gt;It failed spectacularly!&lt;/strong&gt;  I did not configure this project to succeed using npm.  I needed to make simple changes to &lt;code&gt;tsconfig.json&lt;/code&gt; and &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Summary of &lt;code&gt;tsconfig.json&lt;/code&gt; changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;"declaration": true&lt;/code&gt; to create &lt;code&gt;.d.ts&lt;/code&gt; definition file.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;"outDir": "dist"&lt;/code&gt; to have your output sent to a dist/ folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Summary of &lt;code&gt;package.json&lt;/code&gt; changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;"main": "dist/index.js","types": "dist/index.d.ts"&lt;/code&gt; to use dist/ directory for the main entry point and where Typescript should look for &lt;code&gt;.d.ts&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;"build": "tsc"&lt;/code&gt; a build script for Typescript.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Writing a JSON Parser is simple
&lt;/h3&gt;

&lt;p&gt;If you were ever wondered how a Parser works I encourage you to read through this code as a simple example.  The parser consists of 3 main components, the Lexer, Parser, and JSONBuilder. &lt;br&gt;
NOTE: The parser needs to handle exponential numbers and strings with '\' backslash to be complete.&lt;/p&gt;
&lt;h4&gt;
  
  
  Lexer
&lt;/h4&gt;

&lt;p&gt;The job of the Lexer is to break the parts of the string into tokens. For JSON we look for the following tokens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;eTokens&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;BEGIN_ARRAY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// left square bracket&lt;/span&gt;
  &lt;span class="nx"&gt;BEGIN_OBJECT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// left curly bracket&lt;/span&gt;
  &lt;span class="nx"&gt;END_ARRAY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// right square bracket&lt;/span&gt;
  &lt;span class="nx"&gt;END_OBJECT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// right curly bracket&lt;/span&gt;
  &lt;span class="nx"&gt;COLON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;COMMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;TRUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TRUE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FALSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FALSE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NULL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;NUMBER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NUMBER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;STRING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;STRING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;EOF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EOF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Parser
&lt;/h4&gt;

&lt;p&gt;The goal of the parser is to find structure in the stream of tokens and implement our grammer. I choose to define an Abstract Syntax Tree (AST) to represent an intermediate form of the JSON string. I choose for the AST to include 4 Nodes:&lt;/p&gt;

&lt;p&gt;jObject - to represent the object&lt;br&gt;
jArray - to represent the array&lt;br&gt;
jNameValue - to represent a name - value pair&lt;br&gt;
jPrimative - to represent a number, string, true, false, or null&lt;/p&gt;

&lt;p&gt;The Parser implements the following JSON Grammer to build the AST.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value : object
| array
| NUMBER
| STRING
| TRUE
| FALSE
| NULL

object : BEGIN_OBJECT name_value_list END_OBJECT

array : BEGIN_ARRAY value_list END_ARRAY

name_value_list: name_value
| name_value COMMA name_value_list

name_value: string COLON value

value_list: value
| value COMMA value_list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  JSONBuilder
&lt;/h4&gt;

&lt;p&gt;The JSONBuilder walks the AST and builds the Javascript representation of the JSON string.  &lt;/p&gt;

&lt;p&gt;If you are interested in the code you can find it in github &lt;a href="https://github.com/clarkgrg/ts-jsonparse"&gt;ts-jsonparse&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>npm</category>
      <category>practice</category>
    </item>
  </channel>
</rss>
