Recursive parser from Binary to JSON outputYet another JSON parser and serializer for Qt, but with additional featuresA JavaScript VM that interprets code written in JSONJSON C++14 library API/implementationGenerate URLs from a complex JSON object using recursionC# Regex to extract bug ID from Bugzilla JSON responseExcel VBA to parse JSON out of Google Maps APIJavacript code to flatten JSON via recursion with conditional logicOptimize function for assigning existing 3D array values to values of keys in array of objectsLooping JSON in WebAPI Controller and Add new PropertyRecursively generating the look-and-say sequence

What to do when during a meeting client people start to fight (even physically) with each others?

Why do Australian milk farmers need to protest supermarkets' milk price?

Confusion with the nameplate of an induction motor

Provisioning profile doesn't include the application-identifier and keychain-access-groups entitlements

How is the Swiss post e-voting system supposed to work, and how was it wrong?

Can't remove a file with file mode bits a+rw

How does airport security verify that you can carry a battery bank over 100 Wh?

What is the likely impact on flights of grounding an entire aircraft series?

Why don't MCU characters ever seem to have language issues?

Should we release the security issues we found in our product as CVE or we can just update those on weekly release notes?

Running a subshell from the middle of the current command

What is the dot in “1.2.4."

Good for you! in Russian

Who is our nearest neighbor

Recursive parser from Binary to JSON output

Making a sword in the stone, in a medieval world without magic

How to discourage/prevent PCs from using door choke-points?

Can someone explain what is being said here in color publishing in the American Mathematical Monthly?

Sword in the Stone story where the sword was held in place by electromagnets

What exactly is the purpose of connection links straped between the rocket and the launch pad

Rejected in 4th interview round citing insufficient years of experience

Is this animal really missing?

Fourth person (in Slavey language)

what does the apostrophe mean in this notation?



Recursive parser from Binary to JSON output


Yet another JSON parser and serializer for Qt, but with additional featuresA JavaScript VM that interprets code written in JSONJSON C++14 library API/implementationGenerate URLs from a complex JSON object using recursionC# Regex to extract bug ID from Bugzilla JSON responseExcel VBA to parse JSON out of Google Maps APIJavacript code to flatten JSON via recursion with conditional logicOptimize function for assigning existing 3D array values to values of keys in array of objectsLooping JSON in WebAPI Controller and Add new PropertyRecursively generating the look-and-say sequence













5












$begingroup$


Background



I got this interview test and got declined due to not meeting their expectations, but never got a reason on what was bad and how they solved it. I want to improve and learn something out of it.



Question
How can this be better written and what is badly written?



Assignment description



To optimize the amount of data sent between the web browser to the web server
a "clever" Javascript developer came up with the idea to translate JSON objects
into binary format in the application and send them to the server. Faced with
the fact that the Javascript is released in its final version to the customer
it is now your task to develop the parser on the back end system.



A JSON object is a hierarchy of key-value pairs where a value in its turn can
contain new key-value pairs. It consists of four basic types: numbers, strings,
arrays and dictionaries. An array is a list of values and a dictionay is a list
of key-value pairs. The key can only be of the type number or string while a
value can be of any type.



A JSON object always starts with a value.



An example JSON object can look like:




'firstName': 'John',
'lastName': 'Smith',
'age': 25,
'address':
'streetAddress': '21 2nd Street',
'city': 'New York',
'state': 'NY',
'postalCode': '10021'
,
'phoneNumber': [
'type': 'home', 'number': '212 555-1234' ,
'type': 'fax', 'number': '646 555-4567'
]



A number is printed in decimal without any decoration.
Example: 25



A string is printed in ASCII with single quotes in the start and end of the
string.
Example: 'test'



A key-value pair is printed as key followed by colon (:), a space ( ) and the
value.
Example: 'a': 67



A dictionary starts and ends with curly brackets ( and ) and then has a
comma (,) separated list of key-value pairs.
Example: 'name': 'Joe', 'age': 31



An array starts and ends with square brackets ([ and ]) and then has a
comma (,) separated list of values.
Example: [ 'hello', 56, 'world' ]



The binary representation of the JSON object contains a one byte identifier
that describes the type of the data to follow and is then immediately followed
by the data.



The identifiers and their types are as follows:



Identifier Type Description
0x01 Number 4 bytes signed integer in big endian byte order.
0x02 String N ASCII characters terminated by 0x00.
0x05 List Amount of items as a number followed by N values
0x06 Dictionary Amount of items as a number followed by N
key-value pairs


The program's task is to parse a binary file and prints it as human readable
text. It should read the data from standard input and writes it the result to
standard output.



Look at the files 'input_x' and their respective 'result_x' for examples of
input and output. More background can be found on e.g. www.json.org



Input_4 binary



firstsecondvalue for seconddeepinteger as keymixit is possible to mix integers and strings#Eg


My solution



public class Main 

private static String INPUT_FILENAME = "input_4";
private static String OUTPUT_FILENAME = "result_4";

private static String RESOURCE_INPUT_PATH = "src/main/resources/input/";
private static String RESOURCE_OUTPUT_PATH = "src/main/resources/output/";

public static void main(String[] args)
File resourcesDirectory = new File(String.format("%s%s", RESOURCE_INPUT_PATH, INPUT_FILENAME));
File file = new File(resourcesDirectory.getAbsolutePath());

try
byte[] byteArray = Files.readAllBytes(file.toPath());

RecursiveParser recursiveParser = new RecursiveParser();

try
String result = recursiveParser.parse(byteArray, 0, false).toString();

String prettyPrinted = prettyPrint(result);
BufferedWriter writer = new BufferedWriter(
new FileWriter(
new File(
String.format("%s%s%s", RESOURCE_OUTPUT_PATH, OUTPUT_FILENAME, ".json")
)
)
);
writer.write(prettyPrinted);

writer.close();
catch (JSONException e)
e.printStackTrace();

catch (IOException e)
e.printStackTrace();



private static String prettyPrint(String data) throws JSONException
Object json = new JSONTokener(data).nextValue();
if (json instanceof JSONObject)
return (new JSONObject(data)).toString(4);

else if (json instanceof JSONArray)
return (new JSONArray(data)).toString(4);
else
return data; // nothing to pretty print





class RecursiveParser 
private static int TERMINATE = 0x00;

private static int NUMBER = 0x01; // Number 4 bytes signed integer in big endian byte order.
private static int STRING = 0x02; // String N ASCII characters terminated by 0x00.
private static int LIST = 0x05; // List Amount of items as a number followed by N values
private static int DICTIONARY = 0x06; // Dictionary Amount of items as a number followed by N key-value pairs

Object parse(byte[] byteArray, int index, boolean hasSub) throws JSONException
for(; index < byteArray.length; index++)
if(byteArray[index] == NUMBER)
return getNumber(byteArray, index);

if(byteArray[index] == STRING)
return getString(byteArray, index);

if(byteArray[index] == LIST)
return getList(byteArray, index, hasSub);

if(byteArray[index] == DICTIONARY)
return getDictionary(byteArray, index, hasSub);


return null; // should never get here


private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException
index++; // move to size after type because dictionary size

int dictionarySize = (int)parse(byteArray, index, hasSub);
index += ByteBuffer.allocate(4).putInt(dictionarySize).array().length;

JSONWriter jsonWriter = new JSONStringer()
.object();

for(int i = 0; i < dictionarySize; i++) byteArray[index] == LIST);

Object value = parse(byteArray, index, hasSub);

int valueLength = 0;
if (value instanceof Integer)
jsonWriter.value(value);
valueLength += ByteBuffer.allocate(4).putInt((Integer) value).array().length;
else if (value instanceof String)
jsonWriter.value(value);
valueLength += String.valueOf(value).getBytes().length + 1;
else if (value instanceof AbstractMap.SimpleEntry)
valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());


index += valueLength;


jsonWriter
.endObject();

return hasSub && index != (byteArray.length - 1) ? new AbstractMap.SimpleEntry<>(index, new JSONObject(jsonWriter.toString())) : new JSONObject(jsonWriter.toString());


private Object getList(byte[] byteArray, int index, boolean hasSub) throws JSONException
index++; // move to size after type because list size

int listSize = (int)parse(byteArray, index, hasSub);
index += ByteBuffer.allocate(4).putInt(listSize).array().length;

JSONWriter jsonWriter = new JSONStringer().array();
for(int i = 0; i < listSize; i++)
jsonWriter.endArray();

return hasSub && index != (byteArray.length - 1) ? new AbstractMap.SimpleEntry<>(index, new JSONArray(jsonWriter.toString())) : new JSONArray(jsonWriter.toString());


private String getString(byte[] byteArray, int index)
int start = index + 1; // move to next value after type
StringBuilder value = new StringBuilder();
for(int i = start; i < byteArray.length; i++)
if(byteArray[i] == TERMINATE)
break;

value.append((char)byteArray[i]);

return value.toString();


private int getNumber(byte[] byteArray, int index)
int start = index + 1; // move to next value after type
int offset = start + 4;

byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

return new BigInteger(numberByteArray).intValue();




Result_4 output




"5": 25,
"deep":
"1": "integer as key",
"2": "4": 19088743,
"mix": "it is possible to mix integers and strings"
,
"first": 16777216,
"second": "value for second"










share|improve this question









New contributor




Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$
















    5












    $begingroup$


    Background



    I got this interview test and got declined due to not meeting their expectations, but never got a reason on what was bad and how they solved it. I want to improve and learn something out of it.



    Question
    How can this be better written and what is badly written?



    Assignment description



    To optimize the amount of data sent between the web browser to the web server
    a "clever" Javascript developer came up with the idea to translate JSON objects
    into binary format in the application and send them to the server. Faced with
    the fact that the Javascript is released in its final version to the customer
    it is now your task to develop the parser on the back end system.



    A JSON object is a hierarchy of key-value pairs where a value in its turn can
    contain new key-value pairs. It consists of four basic types: numbers, strings,
    arrays and dictionaries. An array is a list of values and a dictionay is a list
    of key-value pairs. The key can only be of the type number or string while a
    value can be of any type.



    A JSON object always starts with a value.



    An example JSON object can look like:




    'firstName': 'John',
    'lastName': 'Smith',
    'age': 25,
    'address':
    'streetAddress': '21 2nd Street',
    'city': 'New York',
    'state': 'NY',
    'postalCode': '10021'
    ,
    'phoneNumber': [
    'type': 'home', 'number': '212 555-1234' ,
    'type': 'fax', 'number': '646 555-4567'
    ]



    A number is printed in decimal without any decoration.
    Example: 25



    A string is printed in ASCII with single quotes in the start and end of the
    string.
    Example: 'test'



    A key-value pair is printed as key followed by colon (:), a space ( ) and the
    value.
    Example: 'a': 67



    A dictionary starts and ends with curly brackets ( and ) and then has a
    comma (,) separated list of key-value pairs.
    Example: 'name': 'Joe', 'age': 31



    An array starts and ends with square brackets ([ and ]) and then has a
    comma (,) separated list of values.
    Example: [ 'hello', 56, 'world' ]



    The binary representation of the JSON object contains a one byte identifier
    that describes the type of the data to follow and is then immediately followed
    by the data.



    The identifiers and their types are as follows:



    Identifier Type Description
    0x01 Number 4 bytes signed integer in big endian byte order.
    0x02 String N ASCII characters terminated by 0x00.
    0x05 List Amount of items as a number followed by N values
    0x06 Dictionary Amount of items as a number followed by N
    key-value pairs


    The program's task is to parse a binary file and prints it as human readable
    text. It should read the data from standard input and writes it the result to
    standard output.



    Look at the files 'input_x' and their respective 'result_x' for examples of
    input and output. More background can be found on e.g. www.json.org



    Input_4 binary



    firstsecondvalue for seconddeepinteger as keymixit is possible to mix integers and strings#Eg


    My solution



    public class Main 

    private static String INPUT_FILENAME = "input_4";
    private static String OUTPUT_FILENAME = "result_4";

    private static String RESOURCE_INPUT_PATH = "src/main/resources/input/";
    private static String RESOURCE_OUTPUT_PATH = "src/main/resources/output/";

    public static void main(String[] args)
    File resourcesDirectory = new File(String.format("%s%s", RESOURCE_INPUT_PATH, INPUT_FILENAME));
    File file = new File(resourcesDirectory.getAbsolutePath());

    try
    byte[] byteArray = Files.readAllBytes(file.toPath());

    RecursiveParser recursiveParser = new RecursiveParser();

    try
    String result = recursiveParser.parse(byteArray, 0, false).toString();

    String prettyPrinted = prettyPrint(result);
    BufferedWriter writer = new BufferedWriter(
    new FileWriter(
    new File(
    String.format("%s%s%s", RESOURCE_OUTPUT_PATH, OUTPUT_FILENAME, ".json")
    )
    )
    );
    writer.write(prettyPrinted);

    writer.close();
    catch (JSONException e)
    e.printStackTrace();

    catch (IOException e)
    e.printStackTrace();



    private static String prettyPrint(String data) throws JSONException
    Object json = new JSONTokener(data).nextValue();
    if (json instanceof JSONObject)
    return (new JSONObject(data)).toString(4);

    else if (json instanceof JSONArray)
    return (new JSONArray(data)).toString(4);
    else
    return data; // nothing to pretty print





    class RecursiveParser 
    private static int TERMINATE = 0x00;

    private static int NUMBER = 0x01; // Number 4 bytes signed integer in big endian byte order.
    private static int STRING = 0x02; // String N ASCII characters terminated by 0x00.
    private static int LIST = 0x05; // List Amount of items as a number followed by N values
    private static int DICTIONARY = 0x06; // Dictionary Amount of items as a number followed by N key-value pairs

    Object parse(byte[] byteArray, int index, boolean hasSub) throws JSONException
    for(; index < byteArray.length; index++)
    if(byteArray[index] == NUMBER)
    return getNumber(byteArray, index);

    if(byteArray[index] == STRING)
    return getString(byteArray, index);

    if(byteArray[index] == LIST)
    return getList(byteArray, index, hasSub);

    if(byteArray[index] == DICTIONARY)
    return getDictionary(byteArray, index, hasSub);


    return null; // should never get here


    private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException
    index++; // move to size after type because dictionary size

    int dictionarySize = (int)parse(byteArray, index, hasSub);
    index += ByteBuffer.allocate(4).putInt(dictionarySize).array().length;

    JSONWriter jsonWriter = new JSONStringer()
    .object();

    for(int i = 0; i < dictionarySize; i++) byteArray[index] == LIST);

    Object value = parse(byteArray, index, hasSub);

    int valueLength = 0;
    if (value instanceof Integer)
    jsonWriter.value(value);
    valueLength += ByteBuffer.allocate(4).putInt((Integer) value).array().length;
    else if (value instanceof String)
    jsonWriter.value(value);
    valueLength += String.valueOf(value).getBytes().length + 1;
    else if (value instanceof AbstractMap.SimpleEntry)
    valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
    jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());


    index += valueLength;


    jsonWriter
    .endObject();

    return hasSub && index != (byteArray.length - 1) ? new AbstractMap.SimpleEntry<>(index, new JSONObject(jsonWriter.toString())) : new JSONObject(jsonWriter.toString());


    private Object getList(byte[] byteArray, int index, boolean hasSub) throws JSONException
    index++; // move to size after type because list size

    int listSize = (int)parse(byteArray, index, hasSub);
    index += ByteBuffer.allocate(4).putInt(listSize).array().length;

    JSONWriter jsonWriter = new JSONStringer().array();
    for(int i = 0; i < listSize; i++)
    jsonWriter.endArray();

    return hasSub && index != (byteArray.length - 1) ? new AbstractMap.SimpleEntry<>(index, new JSONArray(jsonWriter.toString())) : new JSONArray(jsonWriter.toString());


    private String getString(byte[] byteArray, int index)
    int start = index + 1; // move to next value after type
    StringBuilder value = new StringBuilder();
    for(int i = start; i < byteArray.length; i++)
    if(byteArray[i] == TERMINATE)
    break;

    value.append((char)byteArray[i]);

    return value.toString();


    private int getNumber(byte[] byteArray, int index)
    int start = index + 1; // move to next value after type
    int offset = start + 4;

    byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

    return new BigInteger(numberByteArray).intValue();




    Result_4 output




    "5": 25,
    "deep":
    "1": "integer as key",
    "2": "4": 19088743,
    "mix": "it is possible to mix integers and strings"
    ,
    "first": 16777216,
    "second": "value for second"










    share|improve this question









    New contributor




    Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$














      5












      5








      5





      $begingroup$


      Background



      I got this interview test and got declined due to not meeting their expectations, but never got a reason on what was bad and how they solved it. I want to improve and learn something out of it.



      Question
      How can this be better written and what is badly written?



      Assignment description



      To optimize the amount of data sent between the web browser to the web server
      a "clever" Javascript developer came up with the idea to translate JSON objects
      into binary format in the application and send them to the server. Faced with
      the fact that the Javascript is released in its final version to the customer
      it is now your task to develop the parser on the back end system.



      A JSON object is a hierarchy of key-value pairs where a value in its turn can
      contain new key-value pairs. It consists of four basic types: numbers, strings,
      arrays and dictionaries. An array is a list of values and a dictionay is a list
      of key-value pairs. The key can only be of the type number or string while a
      value can be of any type.



      A JSON object always starts with a value.



      An example JSON object can look like:




      'firstName': 'John',
      'lastName': 'Smith',
      'age': 25,
      'address':
      'streetAddress': '21 2nd Street',
      'city': 'New York',
      'state': 'NY',
      'postalCode': '10021'
      ,
      'phoneNumber': [
      'type': 'home', 'number': '212 555-1234' ,
      'type': 'fax', 'number': '646 555-4567'
      ]



      A number is printed in decimal without any decoration.
      Example: 25



      A string is printed in ASCII with single quotes in the start and end of the
      string.
      Example: 'test'



      A key-value pair is printed as key followed by colon (:), a space ( ) and the
      value.
      Example: 'a': 67



      A dictionary starts and ends with curly brackets ( and ) and then has a
      comma (,) separated list of key-value pairs.
      Example: 'name': 'Joe', 'age': 31



      An array starts and ends with square brackets ([ and ]) and then has a
      comma (,) separated list of values.
      Example: [ 'hello', 56, 'world' ]



      The binary representation of the JSON object contains a one byte identifier
      that describes the type of the data to follow and is then immediately followed
      by the data.



      The identifiers and their types are as follows:



      Identifier Type Description
      0x01 Number 4 bytes signed integer in big endian byte order.
      0x02 String N ASCII characters terminated by 0x00.
      0x05 List Amount of items as a number followed by N values
      0x06 Dictionary Amount of items as a number followed by N
      key-value pairs


      The program's task is to parse a binary file and prints it as human readable
      text. It should read the data from standard input and writes it the result to
      standard output.



      Look at the files 'input_x' and their respective 'result_x' for examples of
      input and output. More background can be found on e.g. www.json.org



      Input_4 binary



      firstsecondvalue for seconddeepinteger as keymixit is possible to mix integers and strings#Eg


      My solution



      public class Main 

      private static String INPUT_FILENAME = "input_4";
      private static String OUTPUT_FILENAME = "result_4";

      private static String RESOURCE_INPUT_PATH = "src/main/resources/input/";
      private static String RESOURCE_OUTPUT_PATH = "src/main/resources/output/";

      public static void main(String[] args)
      File resourcesDirectory = new File(String.format("%s%s", RESOURCE_INPUT_PATH, INPUT_FILENAME));
      File file = new File(resourcesDirectory.getAbsolutePath());

      try
      byte[] byteArray = Files.readAllBytes(file.toPath());

      RecursiveParser recursiveParser = new RecursiveParser();

      try
      String result = recursiveParser.parse(byteArray, 0, false).toString();

      String prettyPrinted = prettyPrint(result);
      BufferedWriter writer = new BufferedWriter(
      new FileWriter(
      new File(
      String.format("%s%s%s", RESOURCE_OUTPUT_PATH, OUTPUT_FILENAME, ".json")
      )
      )
      );
      writer.write(prettyPrinted);

      writer.close();
      catch (JSONException e)
      e.printStackTrace();

      catch (IOException e)
      e.printStackTrace();



      private static String prettyPrint(String data) throws JSONException
      Object json = new JSONTokener(data).nextValue();
      if (json instanceof JSONObject)
      return (new JSONObject(data)).toString(4);

      else if (json instanceof JSONArray)
      return (new JSONArray(data)).toString(4);
      else
      return data; // nothing to pretty print





      class RecursiveParser 
      private static int TERMINATE = 0x00;

      private static int NUMBER = 0x01; // Number 4 bytes signed integer in big endian byte order.
      private static int STRING = 0x02; // String N ASCII characters terminated by 0x00.
      private static int LIST = 0x05; // List Amount of items as a number followed by N values
      private static int DICTIONARY = 0x06; // Dictionary Amount of items as a number followed by N key-value pairs

      Object parse(byte[] byteArray, int index, boolean hasSub) throws JSONException
      for(; index < byteArray.length; index++)
      if(byteArray[index] == NUMBER)
      return getNumber(byteArray, index);

      if(byteArray[index] == STRING)
      return getString(byteArray, index);

      if(byteArray[index] == LIST)
      return getList(byteArray, index, hasSub);

      if(byteArray[index] == DICTIONARY)
      return getDictionary(byteArray, index, hasSub);


      return null; // should never get here


      private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException
      index++; // move to size after type because dictionary size

      int dictionarySize = (int)parse(byteArray, index, hasSub);
      index += ByteBuffer.allocate(4).putInt(dictionarySize).array().length;

      JSONWriter jsonWriter = new JSONStringer()
      .object();

      for(int i = 0; i < dictionarySize; i++) byteArray[index] == LIST);

      Object value = parse(byteArray, index, hasSub);

      int valueLength = 0;
      if (value instanceof Integer)
      jsonWriter.value(value);
      valueLength += ByteBuffer.allocate(4).putInt((Integer) value).array().length;
      else if (value instanceof String)
      jsonWriter.value(value);
      valueLength += String.valueOf(value).getBytes().length + 1;
      else if (value instanceof AbstractMap.SimpleEntry)
      valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
      jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());


      index += valueLength;


      jsonWriter
      .endObject();

      return hasSub && index != (byteArray.length - 1) ? new AbstractMap.SimpleEntry<>(index, new JSONObject(jsonWriter.toString())) : new JSONObject(jsonWriter.toString());


      private Object getList(byte[] byteArray, int index, boolean hasSub) throws JSONException
      index++; // move to size after type because list size

      int listSize = (int)parse(byteArray, index, hasSub);
      index += ByteBuffer.allocate(4).putInt(listSize).array().length;

      JSONWriter jsonWriter = new JSONStringer().array();
      for(int i = 0; i < listSize; i++)
      jsonWriter.endArray();

      return hasSub && index != (byteArray.length - 1) ? new AbstractMap.SimpleEntry<>(index, new JSONArray(jsonWriter.toString())) : new JSONArray(jsonWriter.toString());


      private String getString(byte[] byteArray, int index)
      int start = index + 1; // move to next value after type
      StringBuilder value = new StringBuilder();
      for(int i = start; i < byteArray.length; i++)
      if(byteArray[i] == TERMINATE)
      break;

      value.append((char)byteArray[i]);

      return value.toString();


      private int getNumber(byte[] byteArray, int index)
      int start = index + 1; // move to next value after type
      int offset = start + 4;

      byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

      return new BigInteger(numberByteArray).intValue();




      Result_4 output




      "5": 25,
      "deep":
      "1": "integer as key",
      "2": "4": 19088743,
      "mix": "it is possible to mix integers and strings"
      ,
      "first": 16777216,
      "second": "value for second"










      share|improve this question









      New contributor




      Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      Background



      I got this interview test and got declined due to not meeting their expectations, but never got a reason on what was bad and how they solved it. I want to improve and learn something out of it.



      Question
      How can this be better written and what is badly written?



      Assignment description



      To optimize the amount of data sent between the web browser to the web server
      a "clever" Javascript developer came up with the idea to translate JSON objects
      into binary format in the application and send them to the server. Faced with
      the fact that the Javascript is released in its final version to the customer
      it is now your task to develop the parser on the back end system.



      A JSON object is a hierarchy of key-value pairs where a value in its turn can
      contain new key-value pairs. It consists of four basic types: numbers, strings,
      arrays and dictionaries. An array is a list of values and a dictionay is a list
      of key-value pairs. The key can only be of the type number or string while a
      value can be of any type.



      A JSON object always starts with a value.



      An example JSON object can look like:




      'firstName': 'John',
      'lastName': 'Smith',
      'age': 25,
      'address':
      'streetAddress': '21 2nd Street',
      'city': 'New York',
      'state': 'NY',
      'postalCode': '10021'
      ,
      'phoneNumber': [
      'type': 'home', 'number': '212 555-1234' ,
      'type': 'fax', 'number': '646 555-4567'
      ]



      A number is printed in decimal without any decoration.
      Example: 25



      A string is printed in ASCII with single quotes in the start and end of the
      string.
      Example: 'test'



      A key-value pair is printed as key followed by colon (:), a space ( ) and the
      value.
      Example: 'a': 67



      A dictionary starts and ends with curly brackets ( and ) and then has a
      comma (,) separated list of key-value pairs.
      Example: 'name': 'Joe', 'age': 31



      An array starts and ends with square brackets ([ and ]) and then has a
      comma (,) separated list of values.
      Example: [ 'hello', 56, 'world' ]



      The binary representation of the JSON object contains a one byte identifier
      that describes the type of the data to follow and is then immediately followed
      by the data.



      The identifiers and their types are as follows:



      Identifier Type Description
      0x01 Number 4 bytes signed integer in big endian byte order.
      0x02 String N ASCII characters terminated by 0x00.
      0x05 List Amount of items as a number followed by N values
      0x06 Dictionary Amount of items as a number followed by N
      key-value pairs


      The program's task is to parse a binary file and prints it as human readable
      text. It should read the data from standard input and writes it the result to
      standard output.



      Look at the files 'input_x' and their respective 'result_x' for examples of
      input and output. More background can be found on e.g. www.json.org



      Input_4 binary



      firstsecondvalue for seconddeepinteger as keymixit is possible to mix integers and strings#Eg


      My solution



      public class Main 

      private static String INPUT_FILENAME = "input_4";
      private static String OUTPUT_FILENAME = "result_4";

      private static String RESOURCE_INPUT_PATH = "src/main/resources/input/";
      private static String RESOURCE_OUTPUT_PATH = "src/main/resources/output/";

      public static void main(String[] args)
      File resourcesDirectory = new File(String.format("%s%s", RESOURCE_INPUT_PATH, INPUT_FILENAME));
      File file = new File(resourcesDirectory.getAbsolutePath());

      try
      byte[] byteArray = Files.readAllBytes(file.toPath());

      RecursiveParser recursiveParser = new RecursiveParser();

      try
      String result = recursiveParser.parse(byteArray, 0, false).toString();

      String prettyPrinted = prettyPrint(result);
      BufferedWriter writer = new BufferedWriter(
      new FileWriter(
      new File(
      String.format("%s%s%s", RESOURCE_OUTPUT_PATH, OUTPUT_FILENAME, ".json")
      )
      )
      );
      writer.write(prettyPrinted);

      writer.close();
      catch (JSONException e)
      e.printStackTrace();

      catch (IOException e)
      e.printStackTrace();



      private static String prettyPrint(String data) throws JSONException
      Object json = new JSONTokener(data).nextValue();
      if (json instanceof JSONObject)
      return (new JSONObject(data)).toString(4);

      else if (json instanceof JSONArray)
      return (new JSONArray(data)).toString(4);
      else
      return data; // nothing to pretty print





      class RecursiveParser 
      private static int TERMINATE = 0x00;

      private static int NUMBER = 0x01; // Number 4 bytes signed integer in big endian byte order.
      private static int STRING = 0x02; // String N ASCII characters terminated by 0x00.
      private static int LIST = 0x05; // List Amount of items as a number followed by N values
      private static int DICTIONARY = 0x06; // Dictionary Amount of items as a number followed by N key-value pairs

      Object parse(byte[] byteArray, int index, boolean hasSub) throws JSONException
      for(; index < byteArray.length; index++)
      if(byteArray[index] == NUMBER)
      return getNumber(byteArray, index);

      if(byteArray[index] == STRING)
      return getString(byteArray, index);

      if(byteArray[index] == LIST)
      return getList(byteArray, index, hasSub);

      if(byteArray[index] == DICTIONARY)
      return getDictionary(byteArray, index, hasSub);


      return null; // should never get here


      private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException
      index++; // move to size after type because dictionary size

      int dictionarySize = (int)parse(byteArray, index, hasSub);
      index += ByteBuffer.allocate(4).putInt(dictionarySize).array().length;

      JSONWriter jsonWriter = new JSONStringer()
      .object();

      for(int i = 0; i < dictionarySize; i++) byteArray[index] == LIST);

      Object value = parse(byteArray, index, hasSub);

      int valueLength = 0;
      if (value instanceof Integer)
      jsonWriter.value(value);
      valueLength += ByteBuffer.allocate(4).putInt((Integer) value).array().length;
      else if (value instanceof String)
      jsonWriter.value(value);
      valueLength += String.valueOf(value).getBytes().length + 1;
      else if (value instanceof AbstractMap.SimpleEntry)
      valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
      jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());


      index += valueLength;


      jsonWriter
      .endObject();

      return hasSub && index != (byteArray.length - 1) ? new AbstractMap.SimpleEntry<>(index, new JSONObject(jsonWriter.toString())) : new JSONObject(jsonWriter.toString());


      private Object getList(byte[] byteArray, int index, boolean hasSub) throws JSONException
      index++; // move to size after type because list size

      int listSize = (int)parse(byteArray, index, hasSub);
      index += ByteBuffer.allocate(4).putInt(listSize).array().length;

      JSONWriter jsonWriter = new JSONStringer().array();
      for(int i = 0; i < listSize; i++)
      jsonWriter.endArray();

      return hasSub && index != (byteArray.length - 1) ? new AbstractMap.SimpleEntry<>(index, new JSONArray(jsonWriter.toString())) : new JSONArray(jsonWriter.toString());


      private String getString(byte[] byteArray, int index)
      int start = index + 1; // move to next value after type
      StringBuilder value = new StringBuilder();
      for(int i = start; i < byteArray.length; i++)
      if(byteArray[i] == TERMINATE)
      break;

      value.append((char)byteArray[i]);

      return value.toString();


      private int getNumber(byte[] byteArray, int index)
      int start = index + 1; // move to next value after type
      int offset = start + 4;

      byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

      return new BigInteger(numberByteArray).intValue();




      Result_4 output




      "5": 25,
      "deep":
      "1": "integer as key",
      "2": "4": 19088743,
      "mix": "it is possible to mix integers and strings"
      ,
      "first": 16777216,
      "second": "value for second"







      java recursion interview-questions json






      share|improve this question









      New contributor




      Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 4 hours ago









      422_unprocessable_entity

      2,19831752




      2,19831752






      New contributor




      Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 4 hours ago









      RovdjuretRovdjuret

      1285




      1285




      New contributor




      Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Rovdjuret is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          1 Answer
          1






          active

          oldest

          votes


















          4












          $begingroup$

          There are two points that showed up immediately when looking at your implementation:



          • You missed one of the goals of the task: It should read the data from standard input and writes it the result to standard output.

          • You are reading in the complete binary data into memory and process it from there.

          The latter is a no go, if we're talking about large structures of JSON-data, e.g. containing Base64-encoded binary data of a DVD-image (don't ask ;-) It might be unlikely in a real world example but it might let them come to the conclusion that you're not familiar with stream based processing and had another one how showed that ability which might have led to their decision.



          Some remarks about the actual code:



          Your reading-number-implementation:



          private int getNumber(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          int offset = start + 4;

          byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

          return new BigInteger(numberByteArray).intValue();



          The specification said that a number is a signed integer in big endian order which is exactly how a Java int is defined, so instead of creating temporary arrays and a BigInteger you could simply have used an int and used bit-shifting:



          private int getNumber(byte[] byteArray, int index) = (byteArray[index + 2] & 0xff) < 16;
          ret


          If you had implemented a stream based processing and used a DataInputStream the implementation would have been



          private int getNumber(DataInputStream source) 
          return source.readInt();



          Your reading-text-implementation:



          private String getString(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          StringBuilder value = new StringBuilder();
          for(int i = start; i < byteArray.length; i++)
          if(byteArray[i] == TERMINATE)
          break;

          value.append((char)byteArray[i]);

          return value.toString();



          Not much that can be changed here but for good measure, I'd change (char)byteArray[i] to (char) (byteArray[i] & 0xff). For ASCII-characters that's irrelevant but still ;-)



          In getDictionary:



          private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException byteArray[index] == LIST);
          [...]
          else if (value instanceof AbstractMap.SimpleEntry)
          valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
          jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());



          This code block is duplicated in getList, you should put that into its own method and call it from the two methods. Same is true for the logic with the return-statement. This should be put into its own method so you only need to fix it once in case you find a bug in it.



          General stuff:



          You had to cope with the fact that your get-methods had to return a value and should change the value of the index. That's not possible, so you decided to change the index value in the calling method in dependence of the type of the returned parsed value. This is "not optimal" to say the least.






          share|improve this answer








          New contributor




          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          $endgroup$












          • $begingroup$
            Thank you very much for your review, I see now that this wasn't one of my greatest moments such as missing a obvious requirement. I learned a lot from your review and will bring it into my future assignments. Really appreciate it, cheers!
            $endgroup$
            – Rovdjuret
            3 hours ago










          Your Answer





          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );






          Rovdjuret is a new contributor. Be nice, and check out our Code of Conduct.









          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215361%2frecursive-parser-from-binary-to-json-output%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4












          $begingroup$

          There are two points that showed up immediately when looking at your implementation:



          • You missed one of the goals of the task: It should read the data from standard input and writes it the result to standard output.

          • You are reading in the complete binary data into memory and process it from there.

          The latter is a no go, if we're talking about large structures of JSON-data, e.g. containing Base64-encoded binary data of a DVD-image (don't ask ;-) It might be unlikely in a real world example but it might let them come to the conclusion that you're not familiar with stream based processing and had another one how showed that ability which might have led to their decision.



          Some remarks about the actual code:



          Your reading-number-implementation:



          private int getNumber(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          int offset = start + 4;

          byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

          return new BigInteger(numberByteArray).intValue();



          The specification said that a number is a signed integer in big endian order which is exactly how a Java int is defined, so instead of creating temporary arrays and a BigInteger you could simply have used an int and used bit-shifting:



          private int getNumber(byte[] byteArray, int index) = (byteArray[index + 2] & 0xff) < 16;
          ret


          If you had implemented a stream based processing and used a DataInputStream the implementation would have been



          private int getNumber(DataInputStream source) 
          return source.readInt();



          Your reading-text-implementation:



          private String getString(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          StringBuilder value = new StringBuilder();
          for(int i = start; i < byteArray.length; i++)
          if(byteArray[i] == TERMINATE)
          break;

          value.append((char)byteArray[i]);

          return value.toString();



          Not much that can be changed here but for good measure, I'd change (char)byteArray[i] to (char) (byteArray[i] & 0xff). For ASCII-characters that's irrelevant but still ;-)



          In getDictionary:



          private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException byteArray[index] == LIST);
          [...]
          else if (value instanceof AbstractMap.SimpleEntry)
          valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
          jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());



          This code block is duplicated in getList, you should put that into its own method and call it from the two methods. Same is true for the logic with the return-statement. This should be put into its own method so you only need to fix it once in case you find a bug in it.



          General stuff:



          You had to cope with the fact that your get-methods had to return a value and should change the value of the index. That's not possible, so you decided to change the index value in the calling method in dependence of the type of the returned parsed value. This is "not optimal" to say the least.






          share|improve this answer








          New contributor




          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          $endgroup$












          • $begingroup$
            Thank you very much for your review, I see now that this wasn't one of my greatest moments such as missing a obvious requirement. I learned a lot from your review and will bring it into my future assignments. Really appreciate it, cheers!
            $endgroup$
            – Rovdjuret
            3 hours ago















          4












          $begingroup$

          There are two points that showed up immediately when looking at your implementation:



          • You missed one of the goals of the task: It should read the data from standard input and writes it the result to standard output.

          • You are reading in the complete binary data into memory and process it from there.

          The latter is a no go, if we're talking about large structures of JSON-data, e.g. containing Base64-encoded binary data of a DVD-image (don't ask ;-) It might be unlikely in a real world example but it might let them come to the conclusion that you're not familiar with stream based processing and had another one how showed that ability which might have led to their decision.



          Some remarks about the actual code:



          Your reading-number-implementation:



          private int getNumber(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          int offset = start + 4;

          byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

          return new BigInteger(numberByteArray).intValue();



          The specification said that a number is a signed integer in big endian order which is exactly how a Java int is defined, so instead of creating temporary arrays and a BigInteger you could simply have used an int and used bit-shifting:



          private int getNumber(byte[] byteArray, int index) = (byteArray[index + 2] & 0xff) < 16;
          ret


          If you had implemented a stream based processing and used a DataInputStream the implementation would have been



          private int getNumber(DataInputStream source) 
          return source.readInt();



          Your reading-text-implementation:



          private String getString(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          StringBuilder value = new StringBuilder();
          for(int i = start; i < byteArray.length; i++)
          if(byteArray[i] == TERMINATE)
          break;

          value.append((char)byteArray[i]);

          return value.toString();



          Not much that can be changed here but for good measure, I'd change (char)byteArray[i] to (char) (byteArray[i] & 0xff). For ASCII-characters that's irrelevant but still ;-)



          In getDictionary:



          private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException byteArray[index] == LIST);
          [...]
          else if (value instanceof AbstractMap.SimpleEntry)
          valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
          jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());



          This code block is duplicated in getList, you should put that into its own method and call it from the two methods. Same is true for the logic with the return-statement. This should be put into its own method so you only need to fix it once in case you find a bug in it.



          General stuff:



          You had to cope with the fact that your get-methods had to return a value and should change the value of the index. That's not possible, so you decided to change the index value in the calling method in dependence of the type of the returned parsed value. This is "not optimal" to say the least.






          share|improve this answer








          New contributor




          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          $endgroup$












          • $begingroup$
            Thank you very much for your review, I see now that this wasn't one of my greatest moments such as missing a obvious requirement. I learned a lot from your review and will bring it into my future assignments. Really appreciate it, cheers!
            $endgroup$
            – Rovdjuret
            3 hours ago













          4












          4








          4





          $begingroup$

          There are two points that showed up immediately when looking at your implementation:



          • You missed one of the goals of the task: It should read the data from standard input and writes it the result to standard output.

          • You are reading in the complete binary data into memory and process it from there.

          The latter is a no go, if we're talking about large structures of JSON-data, e.g. containing Base64-encoded binary data of a DVD-image (don't ask ;-) It might be unlikely in a real world example but it might let them come to the conclusion that you're not familiar with stream based processing and had another one how showed that ability which might have led to their decision.



          Some remarks about the actual code:



          Your reading-number-implementation:



          private int getNumber(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          int offset = start + 4;

          byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

          return new BigInteger(numberByteArray).intValue();



          The specification said that a number is a signed integer in big endian order which is exactly how a Java int is defined, so instead of creating temporary arrays and a BigInteger you could simply have used an int and used bit-shifting:



          private int getNumber(byte[] byteArray, int index) = (byteArray[index + 2] & 0xff) < 16;
          ret


          If you had implemented a stream based processing and used a DataInputStream the implementation would have been



          private int getNumber(DataInputStream source) 
          return source.readInt();



          Your reading-text-implementation:



          private String getString(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          StringBuilder value = new StringBuilder();
          for(int i = start; i < byteArray.length; i++)
          if(byteArray[i] == TERMINATE)
          break;

          value.append((char)byteArray[i]);

          return value.toString();



          Not much that can be changed here but for good measure, I'd change (char)byteArray[i] to (char) (byteArray[i] & 0xff). For ASCII-characters that's irrelevant but still ;-)



          In getDictionary:



          private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException byteArray[index] == LIST);
          [...]
          else if (value instanceof AbstractMap.SimpleEntry)
          valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
          jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());



          This code block is duplicated in getList, you should put that into its own method and call it from the two methods. Same is true for the logic with the return-statement. This should be put into its own method so you only need to fix it once in case you find a bug in it.



          General stuff:



          You had to cope with the fact that your get-methods had to return a value and should change the value of the index. That's not possible, so you decided to change the index value in the calling method in dependence of the type of the returned parsed value. This is "not optimal" to say the least.






          share|improve this answer








          New contributor




          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          $endgroup$



          There are two points that showed up immediately when looking at your implementation:



          • You missed one of the goals of the task: It should read the data from standard input and writes it the result to standard output.

          • You are reading in the complete binary data into memory and process it from there.

          The latter is a no go, if we're talking about large structures of JSON-data, e.g. containing Base64-encoded binary data of a DVD-image (don't ask ;-) It might be unlikely in a real world example but it might let them come to the conclusion that you're not familiar with stream based processing and had another one how showed that ability which might have led to their decision.



          Some remarks about the actual code:



          Your reading-number-implementation:



          private int getNumber(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          int offset = start + 4;

          byte[] numberByteArray = Arrays.copyOfRange(byteArray, start, offset);

          return new BigInteger(numberByteArray).intValue();



          The specification said that a number is a signed integer in big endian order which is exactly how a Java int is defined, so instead of creating temporary arrays and a BigInteger you could simply have used an int and used bit-shifting:



          private int getNumber(byte[] byteArray, int index) = (byteArray[index + 2] & 0xff) < 16;
          ret


          If you had implemented a stream based processing and used a DataInputStream the implementation would have been



          private int getNumber(DataInputStream source) 
          return source.readInt();



          Your reading-text-implementation:



          private String getString(byte[] byteArray, int index) 
          int start = index + 1; // move to next value after type
          StringBuilder value = new StringBuilder();
          for(int i = start; i < byteArray.length; i++)
          if(byteArray[i] == TERMINATE)
          break;

          value.append((char)byteArray[i]);

          return value.toString();



          Not much that can be changed here but for good measure, I'd change (char)byteArray[i] to (char) (byteArray[i] & 0xff). For ASCII-characters that's irrelevant but still ;-)



          In getDictionary:



          private Object getDictionary(byte[] byteArray, int index, boolean hasSub) throws JSONException byteArray[index] == LIST);
          [...]
          else if (value instanceof AbstractMap.SimpleEntry)
          valueLength = (int) ((AbstractMap.SimpleEntry) value).getKey() - index;
          jsonWriter.value(((AbstractMap.SimpleEntry) value).getValue());



          This code block is duplicated in getList, you should put that into its own method and call it from the two methods. Same is true for the logic with the return-statement. This should be put into its own method so you only need to fix it once in case you find a bug in it.



          General stuff:



          You had to cope with the fact that your get-methods had to return a value and should change the value of the index. That's not possible, so you decided to change the index value in the calling method in dependence of the type of the returned parsed value. This is "not optimal" to say the least.







          share|improve this answer








          New contributor




          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          share|improve this answer



          share|improve this answer






          New contributor




          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          answered 4 hours ago









          LotharLothar

          1561




          1561




          New contributor




          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.





          New contributor





          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          Lothar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.











          • $begingroup$
            Thank you very much for your review, I see now that this wasn't one of my greatest moments such as missing a obvious requirement. I learned a lot from your review and will bring it into my future assignments. Really appreciate it, cheers!
            $endgroup$
            – Rovdjuret
            3 hours ago
















          • $begingroup$
            Thank you very much for your review, I see now that this wasn't one of my greatest moments such as missing a obvious requirement. I learned a lot from your review and will bring it into my future assignments. Really appreciate it, cheers!
            $endgroup$
            – Rovdjuret
            3 hours ago















          $begingroup$
          Thank you very much for your review, I see now that this wasn't one of my greatest moments such as missing a obvious requirement. I learned a lot from your review and will bring it into my future assignments. Really appreciate it, cheers!
          $endgroup$
          – Rovdjuret
          3 hours ago




          $begingroup$
          Thank you very much for your review, I see now that this wasn't one of my greatest moments such as missing a obvious requirement. I learned a lot from your review and will bring it into my future assignments. Really appreciate it, cheers!
          $endgroup$
          – Rovdjuret
          3 hours ago










          Rovdjuret is a new contributor. Be nice, and check out our Code of Conduct.









          draft saved

          draft discarded


















          Rovdjuret is a new contributor. Be nice, and check out our Code of Conduct.












          Rovdjuret is a new contributor. Be nice, and check out our Code of Conduct.











          Rovdjuret is a new contributor. Be nice, and check out our Code of Conduct.














          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215361%2frecursive-parser-from-binary-to-json-output%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Are there any AGPL-style licences that require source code modifications to be public? Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Announcing the arrival of Valued Associate #679: Cesar Manara Unicorn Meta Zoo #1: Why another podcast?Force derivative works to be publicAre there any GPL like licenses for Apple App Store?Do you violate the GPL if you provide source code that cannot be compiled?GPL - is it distribution to use libraries in an appliance loaned to customers?Distributing App for free which uses GPL'ed codeModifications of server software under GPL, with web/CLI interfaceDoes using an AGPLv3-licensed library prevent me from dual-licensing my own source code?Can I publish only select code under GPLv3 from a private project?Is there published precedent regarding the scope of covered work that uses AGPL software?If MIT licensed code links to GPL licensed code what should be the license of the resulting binary program?If I use a public API endpoint that has its source code licensed under AGPL in my app, do I need to disclose my source?

          2013 GY136 Descoberta | Órbita | Referências Menu de navegação«List Of Centaurs and Scattered-Disk Objects»«List of Known Trans-Neptunian Objects»

          Button changing it's text & action. Good or terrible? The 2019 Stack Overflow Developer Survey Results Are Inchanging text on user mouseoverShould certain functions be “hard to find” for powerusers to discover?Custom liking function - do I need user login?Using different checkbox style for different checkbox behaviorBest Practices: Save and Exit in Software UIInteraction with remote validated formMore efficient UI to progress the user through a complicated process?Designing a popup notice for a gameShould bulk-editing functions be hidden until a table row is selected, or is there a better solution?Is it bad practice to disable (replace) the context menu?