⌛⌛⌛ JSON

Aseta vastauksesi tiedostoihin Node.java (josta valmis pohja annettu), ArrayNode.java, ObjectNode.java ja ValueNode.java kansiossa Round6/json. Muista nyhtää ``student_template_project``sta materiaalit.

Tässä tehtävässä toteutetaan yksinkertainen luokkarakenne JSON-datan luomiseen. Ellet tiedä, mitä JSON on, on korkea aika käydä tutustumassa siihen esim. Wikipediassa.

JSON-data koostuu seuraavanlaisista data-alkioista:

  • Numero. Tässä tehtävässä tyyppinä double.

  • Totuusarvo. Tässä tehtävässä tyyppinä boolean.

  • Merkkijono. Tässä tehtävässä tyyppinä String.

  • Null. Tässä tehtävässä arvona null.

  • Taulukko. Lista, jossa on nolla tai useampia data-alkioita.

  • Objekti. Sanakirjaa muistuttava kokoelma, jossa on nolla tai useampia avain-alkiopareja. Avaimet ovat aina merkkijonoja.

Valmiina annettu Node.java sisältää abstraktin luokan Node, joka toimii tässä tehtävässä JSON-datan alkioiden kattotyyppinä. Toteuta tämän perivät luokat ValueNode, ArrayNode ja ObjectNode siten, että:

  • ValueNode tallettaa sisäänsä numeron, totuusarvon, merkkijonon tai arvon null. Julkiset jäsenet:

    • Rakentimet ValueNode(double value), ValueNode(boolean value) ja ValueNode(String value).

      • Alustavat olion tallettamaan jonkin edellämainituista tyypeistä. Huomaa, että viimeisin sallii myös arvon null tallennuksen (primitiivityyppinä ei voisi antaa null-viitettä).

    • Jäsenfunktiot isNumber(), isBoolean(), isString() ja isNull(), joista kukin palauttaa totuusarvon joka kertoo, onko talletettu arvo funkiota vastaavaa tyyppiä. Esim. isString palauttaa true jos ja vain jos talletettu arvo on merkkijono.

    • Jäsenfunktiot double getNumber(), boolean getBoolean() ja String getString(), joista kukin palauttaa talletetun arvon (jonka oletetaan olevan funktion mukaista tyyppiä). Esim. getNumber palauttaa talletetun numeron double-arvona, ja tässä olisi kutsujan vastuulla ensin varmistaa funktiolla isNumber, että arvo todella on numero ja kutsu on laillinen.

  • ArrayNode tallettaa sisäänsä nolla tai useampaa Node-oliota. Ominaisuudet ja julkiset jäsenet:

    • Toteuttaa rajapinnan Iterable<Node>.

    • Oletusrakennin, joka alustaa tyhjän taulukon (ei vielä sisällä yhtään Node-oliota).

    • Jäsenfunktio void add(Node node), joka lisää annetun Node-olion taulukon loppuun.

    • Jäsenfunktio int size(), joka palauttaa taulukon Node-olioiden lukumäärän.

  • ObjectNode tallettaa sisäänsä nolla tai useampaa avain-alkioparia, missä avaimet ovat merkkijonoja ja alkiot Node-oliota. Ominaisuudet ja julkiset jäsenet:

    • Toteuttaa rajapinnan Iterable<String>.

      • Iteroi kaikkien talletettujen avain-alkioparien avaimet String-merkkijonojen luonnollisessa järjestyksessä.

    • Oletusrakennin, joka alustaa tyhjän JSON-objektin (ei vielä sisällä yhtään avain-alkioparia).

    • Jäsenfunktio Node get(String key), joka palauttaa avainta key vastaavan Node-olion (null, jos sellaista ei ole).

    • Jäsenfunktio void set(String key, Node node), joka lisää parametrien kuvaaman avain-alkioparin. Mahdollinen vanha saman avaimen alkio korvautuu uudella.

    • Jäsenfunktio int size(), joka palauttaa avain-alkioparien lukumäärän.

Luokkien ArrayNode ja ObjectNode toteutukset voivat olla todella yksinkertaisia, jos hyödynnät Javan valmiita säiliöitä järkevästi.

Luokka Node sisältää valmiin funktion printSimple, joka tulostaa sille parametrina annetun Node-olion alaisuuteen talletetut tiedot melko karuna listauksena. Luokassa on lisäksi funktio printJson, jolta puuttuu kunnollinen toteutus. Voit saada tehtävästä 30 pistettä, jos annat funktiolle printJson toteutuksen, joka tuottaa “nätisti” muotoillun JSON-datan rakennetta kuvaavan tulostuksen. Jos jätät tämän funktion toteuttamatta, voit saada 20 pistettä. Tarkista funktiolta printJson odotettu tulostusmuoto esimerkkitulosteista.

Luokka Node sisältää lisäksi valmiit funktiot isValue, isArray ja isObject alkion tyypin tutkimiseen.

Toteutuksen testaus

Voit testata luokkiasi tiedostossa JsonTest.java annetun valmiin testiohjelman ja tiedostoissa output1.txt, output2.txt, output3.txt, output4.txt, output5.txt ja output6.txt annettujen esimerkkitulosteiden avulla. Aseta nämä tiedostot sekä omat luokkatoteutuksesi samaan hakemistoon, käännä ohjelma esim. tapaan javac *.java, ja suorita testit tapaan java JsonTest 1 simple, java JsonTest 2 simple, java JsonTest 3 simple, java JsonTest 4 simple, java JsonTest 3 json ja java JsonTest 4 json. Näiden kuuden suorituksen pitäisi tuottaa tiedostoissa output1.txt, output2.txt, output3.txt, output4.txt, output5.txt ja output6.txt kuvatut tulosteet. Ensimmäiset neljä testiä tulostavat funktiolla printSimple ja viimeiset kaksi funktiolla printJson. Jos toteutat funktion printJson, katso jälkimmäisten kahden testin esimerkkitulosteista, miten sen pitäisi muotoilla tulosteensa. Alla on lisäksi esimerkki siitä, miten printJson tulostaisi toisen testin JSON-datan:

{
  "address": {
    "city": "Tampere",
    "country": "Finland"
  },
  "faculties": [
    {
      "name": "Faculty of Built Environment"
    },
    {
      "name": "Faculty of Education and Culture"
    },
    {
      "name": "Faculty of Engineering and Natural Sciences"
    },
    {
      "name": "Faculty of Information Technology and Communication Sciences"
    },
    {
      "name": "Faculty of Management and Business"
    },
    {
      "name": "Faculty of Medicine and Health Technology"
    },
    {
      "name": "Faculty of Social Sciences"
    }
  ],
  "name": "Tampere University"
}

A+ esittää tässä kohdassa tehtävän palautuslomakkeen.