5.5 XML & JSON
© Γιάννης Κωστάρας
<- | Δ |
XML
Η γλώσσα XML (Extensible Markup Language) είναι μια φορητή, φιλική στον άνθρωπο μορφή για ανταλλαγή δεδομένων μεταξύ προγραμμάτων. Όπως και η πιο γνωστή markup γλώσσα, η HTML (HyperText Markup Language) προέρχεται από το πρότυπο SGML (Standard Generalized Markup Language).
Ένα παράδειγμα αρχείου XML φαίνεται στη συνέχεια (για λόγους ασφαλείας οι κωδικοί θα πρέπει να είναι hashed αλλά για το παράδειγμά μας τους αφήνουμε ως έχει):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<users>
<user userID="123456">
<username>user</username>
<password>pwd</password>
</user>
<user userID="13569">
<username>admin</username>
<password>admin</password>
</user>
</users>
Η 1η γραμμή δηλώνει ότι πρόκειται για αρχείο XML. Οι ετικέττες (tags) χαρακτηρίζουν τα δεδομένα, ενώ μπορούν να δέχονται και γνωρίσματα (attributes). Έτσι, π.χ. στο παραπάνω παράδειγμα, το username
είναι ένα tag ενώ το userID
ένα attribute.
Υπάρχουν 4 κατηγορίες συντακτών (parsers) που μπορούν να επεξεργαστούν αρχεία XML:
- Event Based Push: SAX (Simple API for XML)
- Event Based Pull: StAX (Stream API for XML), XMLPULL
- Δενδρικοί: DOM (Document Object Model), JDOM, dom4j, XOM κ.ά.
- Data Binding: JAXB, Castor, JaxMe κ.ά.
Οι επικυρωτές (validators) επικυρώνουν το κατά πόσο ένα αρχείο XML είναι έγκυρο, π.χ. ότι έχει τις σωστές ετικέττες κλπ. Η σύνταξη ενός αρχείου XML περιγράφεται είτε σε ένα Document Type Definition (DTD) είτε σ’ ένα XML Schema. Οι επικυρωτές ελέγχουν κατά πόσο ένα αρχείο XML είναι σωστά μορφοποιημένο (well formed) (π.χ. ότι υπάρχει μια ριζική ετικέττα, ότι υπάρχει ετικέττα κλεισίματος κλπ.) και έγκυρο (valid) (δηλ. ότι είναι γραμμένο σύμφωνα με τους κανόνες στο DTD ή XML Schema).
Με τη βοήθεια της γλώσσας XSL (Extensible Style Language) μπορούμε να μετατρέψουμε ένα αρχείο XML σε μια άλλη μορφή (π.χ. HTML, PDF κλπ.).
java.xml
Το άρθρωμα java.xml
περιλαμβάνει τους παρακάτω συντάκτες για XML:
- JAXP (Java API for XML Processing) επιτρέπει να χρησιμοποιήσετε βιβλιοθήκες από τρίτους πέραν απ’ αυτές που προσφέρει το JDK
- SAX (Simple API for XML) η υλοποίηση του JDK για αναλυτή SAX
- StAX (Streaming API for XML) όπως ο SAX αλλά χωρίς event handlers
- DOM (W3C Document Object Model API) η υλοποίηση του JDK για αναλυτή DOM
Δυστυχώς, το πολύ γνωστό JAXB (Java Architecture for XML Binding) δεν αποτελεί πλέον μέρος του JDK (JEP 320).
SAX
Υπάρχουν δυο συντάκτες SAX: SAX 1 και SAX 2 (για τον οποίο θα μιλήσουμε εδώ). Ο συντάκτης SAX είναι πιο γρήγορος και χρησιμοποιεί λιγότερη μνήμη από τον DOM καθώς δεν απαιτεί να φορτώσει όλο το αρχείο XML στη μνήμη. Φυσικά, δε μπορούμε να χρησιμοποιήσουμε XPath μ’ αυτόν τον συντάκτη.
Ας δούμε πώς μπορούμε να αναλύσουμε (parse) το πιο πάνω XML αρχείο με τον SAX 2.
Δημιουργήστε ένα νέο έργο Java στο NetBeans (π.χ. XMLParsersApp
με μια κλάση με main()
μέθοδο). Αντιγράψτε/δημιουργήστε το αρχείο XML (users.xml
) στο φάκελο του έργου στο ίδιο επίπεδο με το φάκελο src
(μεταβείτε στην καρτέλα Files αντί για την Projects).
import static java.lang.System.*;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DefaultHandler2;
import org.xml.sax.Attributes;
import org.xml.sax.SAXParseException;
public class SAXParserApp {
public static void main(String[] args) {
parse("users.xml");
}
static void parse(String file) {
SAXParserFactory factory = SAXParserFactory.newInstance(); // newDefaultInstance();
// factory.setNamespaceAware(true);
try {
SAXParser saxParser = factory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setContentHandler(new Handler());
xmlReader.parse(file);
} catch (ParserConfigurationException | SAXException | IOException e) {
Logger.getLogger(SAXParserApp.class.getName()).log(Level.SEVERE, null, e);
}
}
}
Με τη βοήθεια του SAXParserFactory
μπορούμε να λάβουμε έναν SAXParser
. Η μέθοδος SAXParserFactory.newDefaultInstance()
εισήχθηκε στην έκδοση 9 και επιστρέφει την εξ’ορισμού υλοποίηση του συστήματος. Από τον SAXParser
μπορούμε να λάβουμε έναν XMLReader
του οποίου καλούμε τη μέθοδο parse()
παρέχοντάς του το αρχείο XML που θέλουμε ν’ αναλύσουμε. Θα πρέπει προηγουμένως να του παρέχουμε έναν Handler
που θα κάνει τη δουλειά της ανάλυσης και του οποίου ο κώδικας παρέχεται στη συνέχεια:
private static class Handler extends DefaultHandler2 {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
out.printf("<%s", qName);
for (int i = 0; i < attributes.getLength(); i++) {
out.printf(" @%s=%s", attributes.getLocalName(i), attributes.getValue(i));
if (i != attributes.getLength()-1) {
out.print(", ");
}
}
out.println(">");
}
@Override
public void characters(char[] ch, int start, int length) {
for (int i = start; i < start + length; i++) {
out.print(ch[i]);
}
out.println();
}
@Override
public void endElement(String uri, String localName, String qName) {
out.printf("</%s>%n", qName);
}
@Override
public void warning(SAXParseException saxpe) {
out.printf("warning() %s%n", saxpe.toString());
}
@Override
public void error(SAXParseException saxpe) {
out.printf("error() %s%n", saxpe.toString());
}
@Override
public void fatalError(SAXParseException saxpe) {
out.printf("fatalError() %s%n", saxpe.toString());
}
}
Το αποτέλεσμα της εκτέλεσης:
<users>
<user userID=123456>
<username>
user
</username>
<password>
pwd
</password>
</user>
<user userID=13569>
<username>
admin
</username>
<password>
admin
</password>
</user>
</users>
Επεκτείνει τον DefaultHandler2
(SAX2) (ο οποίος υλοποιεί τις διεπαφές ContentHandler, DTDHandler, EntityResolver, ErrorHandler
) και υπερφορτώνει τις μεθόδους:
startElement()
η οποία δηλώνει ότι βρήκε κάποια ετικέττα, π.χ.<user>
και επίσης επεξεργάζεται τα γνωρίσματα (attributes)endElement()
η οποία δηλώνει ότι βρήκε το κλείσιμο κάποιας ετικέττας, π.χ.</user>
characters()
η οποία επεξεργάζεται τα δεδομένα μεταξύ ετικεττών
Υπάρχουν φυσικά πολλές περισσότερες μέθοδοι που επεξεργάζονται τα πάντα όπως μπορείτε να δείτε στο ΑΡΙ αλλά ξεφεύγουν από το σκοπό αυτών των εισαγωγικών μαθημάτων.
Μπορείτε ακόμα να επικυρώσετε το αρχείο users.xml
με βάση κάποιο DTD ή XMLSchema. Το NetBeans σας επιτρέπει να παράγετε εύκολα ένα DTD αρχείο κάνοντας δεξί κλικ στο XML αρχείο σας και επιλέγοντας το μενού Generate DTD. Στη συνέχεια θα πρέπει να κάνετε τις εξής αλλαγές στο πρόγραμμά σας:
public class SAXParserApp {
private final static String FEAT_VAL = "http://xml.org/sax/features/validation";
//...
xmlReader.setFeature(FEAT_VAL, true);
//...
StAX
Είναι παρόμοιος με τον SAX, αλλά αντί να χρειάζεται έναν event handler, επεξεργάζεται επαναληπτικά κάθε στοιχείο σε μια ροή.
Δημιουργήστε μια νέα κλάση StAXParserApp
στο έργο που δημιουργήσατε προηγούμενα στο NetBeans και τη μέθοδο main()
.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import static java.lang.System.out;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
public class StAXParserApp {
public static void main(String[] args) {
parse("users.xml");
}
private static void parse(String file) {
XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false); // εξ' ορισμού είναι true
try (InputStream is = new FileInputStream(new File(file))) {
XMLStreamReader parser = factory.createXMLStreamReader(is);
while (parser.hasNext()) {
int event = parser.next();
switch (event) {
case XMLStreamReader.START_ELEMENT:
out.printf("<%s", parser.getLocalName()); // </element>
if (parser.getAttributeCount() > 0) {
out.printf(" %s=%s", parser.getAttributeName(0), parser.getAttributeValue(0));
}
out.println(">");
break;
case XMLStreamReader.CHARACTERS:
if (parser.hasText()) {
out.printf("%s%n", parser.getText());
}
break;
case XMLStreamReader.END_ELEMENT:
out.printf("</%s>%n", parser.getLocalName()); // </element>
break;
default:
break;
}
}
} catch (IOException | XMLStreamException e) {
e.printStackTrace();
}
}
}
Ο XMLStreamReader
διαθέτει μια σειρά από γεγονότα (events):
XMLStreamReader.START_ELEMENT
XMLStreamReader.CHARACTERS
XMLStreamReader.END_ELEMENT
τα οποία επεξεργαζόμαστε σ’ ένα βρόγχο επανάληψης.
DOM
Δημιουργεί ένα δέντρο ή γράφο στην μνήμη με βάση τα δεδομένα του αρχείου. Απαιτεί πολύ μνήμη για μεγάλα αρχεία.
Για την ανάλυση ενός XML αρχείου με τη βοήθεια του αναλυτή DOM η διαδικασία είναι παρόμοια. Θα πρέπει να δημιουργήσετε έναν DocumentBuilder
τον οποίο λαμβάνετε από ένα DocumentBuilderFactory
μ’ αυτόν στη συνέχεια μπορείτε ν’ αναλύσετε το αρχείο XML.
Δημιουργήστε μια νέα κλάση DOMParserApp
στο έργο που δημιουργήσατε προηγούμενα στο NetBeans και τη μέθοδο main()
.
public class DOMParserApp {
public static void main(String[] args) {
parse("users.xml");
}
private static void parse(String file) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(file);
Element root = doc.getDocumentElement();
processElement(root);
} catch (ParserConfigurationException | SAXException | IOException ex) {
Logger.getLogger(DOMParserApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
To Document
δημιουργεί μια δενδρική μορφή του αρχείου μας στη μνήμη και μπορούμε να ανακτήσουμε το ριζικό στοιχείο, στην περίπτωσή μας το <users>
. Αποτελείται από αντικείμενα που υλοποιούν τη διεπαφή Node
η ιεραρχία των οποίων φαίνεται στην ακόλουθη εικόνα.
Εικόνα 5.5.1 Ιεραρχία κλάσεων DOM
Στη συνέχεια καλούμε την αναδρομική μέθοδο processElement()
για να επεξεργαστούμε το DOM μοντέλο:
/**
* Recursively process each element in DOM.
*
* @param element
*/
private static void processElement(Element element) {
out.printf("<%s", element.getTagName()); // <element>
NamedNodeMap attributes = element.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node attribute = attributes.item(i);
out.printf(" %s=%s", attribute.getNodeName(), attribute.getNodeValue()); // attr=value
}
out.println(">");
var textNode = (Text) element.getFirstChild();
out.printf("%s%n", textNode.getData().trim()); // <element>text</element>
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child instanceof Element) {
var childElement = (Element) child;
processElement(childElement);
}
}
out.printf("</%s>%n", element.getTagName()); // </element>
}
Αποτέλεσμα:
<users>
<user userID=123456>
<username>
user
</username>
<password>
pwd
</password>
</user>
<user userID=13569>
<username>
admin
</username>
<password>
admin
</password>
</user>
</users>
Μπορείτε να χρησιμοποιήσετε και XPath με το DOM για ν’ αναζητήσετε στοιχεία στο αρχείο XML:
private static String find(String path, Document doc) {
String found = "";
XPathFactory xpfactory = XPathFactory.newInstance();
XPath xpath = xpfactory.newXPath();
try {
found = xpath.evaluate(path, doc);
} catch (XPathExpressionException ex) {
Logger.getLogger(DOMParserApp.class.getName()).log(Level.SEVERE, null, ex);
}
return found;
}
Π.χ.
out.println(find("/users/user/username", doc)); // επιστρέφει user
Για καλύτερη απόδοση, μπορείτε να μεταγλωττίσετε (compile) μια έκφραση XPath, αν πρόκειται να τη χρησιμοποιήσετε πολλές φορές, π.χ.:
XPathExpression exp = xPath.compile("//password");
...
NodeList passwords = (NodeList) exp.evaluate(doc, XPathConstants.NODESET);
Μπορείτε επίσης να δημιουργήσετε XML αρχεία. Στο παρακάτω παράδειγμα δείχνουμε πώς μπορείτε να δημιουργήσετε τα περιεχόμενα του users.xml
:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class DOMCreator {
public static void main(String[] args) {
generate("users_.xml");
}
private static void generate(String file) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("users"); // <users>
Element user = doc.createElement("user"); // <user>
user.setAttribute("userID", "123456"); // <user userID="123456">
Element username = doc.createElement("username"); //<username>
username.appendChild(doc.createTextNode("admin")); //admin
user.appendChild(username);
Element password = doc.createElement("password"); //<password>
password.appendChild(doc.createTextNode("admin")); //admin
user.appendChild(password);
root.appendChild(user);
doc.appendChild(root);
writeToFile(doc, file);
} catch (ParserConfigurationException ex) {
Logger.getLogger(DOMParserApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static void writeToFile(Document doc, String file) {
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(doc), new StreamResult(new FileOutputStream(file)));
} catch (TransformerConfigurationException ex) {
Logger.getLogger(DOMCreator.class.getName()).log(Level.SEVERE, null, ex);
} catch (FileNotFoundException | TransformerException ex) {
Logger.getLogger(DOMCreator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Ασφάλεια
Όπως και με την SQL, υπάρχουν και κυβερνοεπιθέσεις για XML.
XML Injection
Όπως και η SQL, έτσι κάποιος κακόβουλος χρήστης μπορεί να εισάγει ειδικά τροποποιημένο XML αρχείο.
Π.χ. έστω το παρακάτω αρχείο από το καλάθι του χρήστη σε μια ιστοσελίδα ηλεκτρονικού εμπορίου:
<item>
<description>iPhone</description>
<price>850.0</price>
<quantity>1</quantity>
</item>
Ένας κακόβουλος χρήστης μπορεί να δώσει στο πεδίο quantity
το παρακάτω:
1</quantity><price>1.0</price><quantity>1
με αποτέλεσμα:
<item>
<description>iPhone</description>
<price>850.0</price>
<quantity>1</quantity><price>1.0</price><quantity>1</quantity>
</item>
Το 2ο πεδίο price
υπερκαλύπτει το 1ο με αποτέλεσμα ν’ αγοράσει το iPhone για 1€ μόνο!
Σ’αυτήν την περίπτωση θα πρέπει να ελέγχεται το πεδίο τιμών των πεδίων, π.χ.
int validate(String sQuantity) {
int quantity = -1; //invalid
try {
quantity = Integer.parseInt(sQuantity);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException(ex);
}
if (quantity > 0 && quantity < 10) {
return quantity;
} else {
return -1;
}
}
Άλλη λύση είναι η χρήση XML Schema ή DTD.
XML External Entity Attacks (XXE)
Κάποιες οντότητες (entities) ενός XML αρχείου μπορεί να προέρχονται από εξωτερικούς πόρους. Π.χ. το παρακάτω αρχείο
<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "file:/dev/tty">
<foo>bar</foo>
προσπαθεί να προσπελάσει το /dev/tty
(ή /dev/random
) με αποτέλεσμα να προκαλεί Denial of Service (DoS) όταν αναλυθεί από το παρακάτω πρόγραμμα:
public class ΧΧΕApp {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
parseXML(new FileInputStream("evil.xml"), new DefaultHandler2());
}
private static void parseXML(InputStream is, DefaultHandler2 defaultHandler)
throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
saxParser.parse(is, defaultHandler);
}
}
Η λύση είναι η χρήση ενός EntityResolver
και ξεφεύγει από τα πλαίσια του εισαγωγικού μαθήματος.
JSON
Μια άλλη αναπαράσταση δεδομένων είναι η μορφή JSON (JavaScript Object Notation). Το JSON μπορεί ν’ αναπαραστήσει δυο δομημένους τύπους: αντικείμενα και συστοιχίες (arrays). Υποστηρίζει τους παρακάτω τύπους δεδομένων: number, string, boolean, array, object, null
. Χρησιμοποιείται συχνά σε εφαρμογές Ajax, υπηρεσίες ιστού REST (RESTful web services) κ.α. Φυσικά, όπως και με την XML, μπορείτε να επικυρώσετε μια δομή JSON σε κάποιο σχήμα (schema) (βλ. schemavalidator και άλλες υλοποιήσεις).
Το Java API for JSON Processing παρέχει τη δυνατότητα να αναλύσετε (parse), παράγετε (generate), μετατρέψετε (transform), και να δημιουργήσετε ερωτήματα (query) δομές JSON. Η JSON απαιτεί λιγότερη πληκτρολόγηση από την XML. Το JEP 198: Light-Weight JSON API για την προσθήκη του JSON API στη Java δεν είναι ακόμα μέρος του JDK. Άλλες βιβλιοθήκες:
- GSon από τη Google
- Jackson
- mJson
- JSON-Simple
- JSON-P που αποτελεί μέρος του JEE
Είδαμε ήδη μια χρήση της JSON στο προηγούμενο μάθημα για επικοινωνία με τη MongoDB. Ένα παράδειγμα JSON φαίνεται παρακάτω:
{
"username": "admin",
"password": "admin",
"blocked": false,
"tries": 2
}
Δημιουργήστε ένα νέο έργο Java στο NetBeans και New –> Other –> JSON File για να δημιουργήσετε ένα νέο κενό αρχείο user.json
και να επικολλήσετε τα ανωτέρω δεδομένα. Αποθηκεύστε το αρχείο στο ίδιο επίπεδο με το φάκελο src
. Δημιουργήστε μια νέα κλάση Java με μια main()
μέθοδο.
Θα χρησιμοποιήσουμε τη βιβλιοθήκη GSon. Κατεβάστε την τελευταία έκδοση της GSon και προσθέστε το αρχείο gson-x.x.x.jar
στις βιβλιοθήκες (Libraries) του έργου.
Για να διαβάσουμε το αρχείο user.json
, δημιουργούμε ένα νέο αντικείμενο GSon
και καλούμε τη μέθοδο .fromJson
παρέχοντας έναν Reader
και την κλάση στην οποία θα μετατραπεί το JSON:
public class JSONGSonApp {
public static void main(String[] args) {
System.out.println(parseJSON("user.json"));
}
private static User parseJSON(String file) {
Gson gson = new Gson();
try (Reader r = new FileReader(file)) {
return gson.fromJson(r, User.class);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
static class User {
private String username;
private String password;
private boolean blocked;
private int tries;
public User(String username, String password, boolean blocked, int tries) {
this.username = username;
this.password = password;
this.blocked = blocked;
this.tries = tries;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public boolean isBlocked() {
return blocked;
}
public int getTries() {
return tries;
}
@Override
public String toString() {
return "User{" + "username=" + username + ", password=" + password + ", blocked=" + blocked + ", tries=" + tries + '}';
}
}
}
Άλλος τρόπος είναι η μετατροπή του σ’ ένα JsonObject
με τη βοήθεια του JsonParser
:
public static void main(String[] args) {
System.out.println(parseAsJsonObject("user.json"));
}
private static JsonObject parseAsJsonObject(String file) {
try (Reader r = new FileReader(file)) {
return new JsonParser().parse(r).getAsJsonObject();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Ένα JsonObject
αποτελείται από ζεύγη key-value
όπου value
είναι τύπου JsonElement
. Μπορούμε ν’ ανακτήσουμε οποιοδήποτε γνώρισμα, π.χ.
JsonObject jsonObject = new JsonParser().parse(r).getAsJsonObject();
jsonObject.get("tries").getAsInt();
Υπάρχουν, εκτός του JsonElement
και τα JsonNull
, JsonArray
και JsonPrimitive
.
Αντίστοιχα, για να γράψετε ένα αντικείμενο User
ως JSON:
public static void main(String[] args) {
User user = new User("admin", "admin", false, 2);
generateJSON(user, "user_.json");
}
private static void generateJSON(Object o, String file) {
Gson gson = new Gson();
try (Writer w = new FileWriter(file)) {
w.append(gson.toJson(o));
} catch (IOException e) {
e.printStackTrace();
}
}
Άλλος τρόπος:
public static void main(String[] args) {
JsonObject userObj = new JsonObject();
userObj.addProperty("username", "user");
userObj.addProperty("password", "user");
userObj.addProperty("blocked", false);
userObj.addProperty("tries", 2);
generateJSON(userObj, "user__.json");
for (String key : userObj.keySet()) {
System.out.println(key + ":" + userObj.get(key));
}
}
private static void generateJSON(JsonObject o, String file) {
Gson gson = new Gson();
try (Writer w = new FileWriter(file)) {
w.append(gson.toJson(o));
} catch (IOException e) {
e.printStackTrace();
}
}
Περίληψη
Σ’ αυτό το μάθημα είδαμε δυο πολύ διάσημες αναπαραστάσεις δεδομένων: XML και JSON και είδαμε πώς μπορούμε να διαβάσουμε και να γράψουμε σ’ αυτές τις μορφές με τη Java.
Ασκήσεις
- Είδαμε πώς να δημιουργήσουμε το
users.xml
με το DOM parser. Επαναλάβετε το ίδιο με τον StAX parser. - Ξαναγράψτε τα παραδείγματα JSON χρησιμοποιώντας τις βιβλιοθήκες mJSon και Jackson.
Πηγές
- Friesen J. (2019), Java XML and JSON, 2nd Ed., APress.
- Horstmann C. S. (2016), Core Java, Volume ΙΙ, 11th Ed., Pearson.
- GSon user guide
- JSON Path
<- | Δ |