18

I am writing a function to check if the input string is valid JSON or valid XML or neither. I found a post here. But obviously the answers in the post are incorrect because they only check if the string starts with < or {, which cannot guarantee the string is valid JSON or valid XML.

I do have a solution myself, which is:

public static String getMsgType(String message) {
    try {
        new ObjectMapper().readTree(message);
        log.info("Message is valid JSON.");
        return "JSON";
    } catch (IOException e) {
        log.info("Message is not valid JSON.");
    }

    try {
        DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(message)));
        log.info("Message is valid XML.");
        return "XML";
    } catch (Exception e) {
        log.info("Message is not valid XML.");
    }

    return null;
}

I am wondering if there is any better or shorter solution? Thanks.

6324
  • 4,678
  • 8
  • 34
  • 63

3 Answers3

7

First of all I dont think you have to reinvent the code for JSON or XML validation. It is already available, well tested and quite optimized.

In case of JSON: you can use JSONObject from Here. Here's demo on that.

In case of XML:You should probably use a DocumentBuilder if you want to check the well formed XML. Demo:

    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(XmlSourceFile);

Try parsing, if it does not fail you got good to go XML. try overloaded methods of dBuilder.parse() according to your suitability

Community
  • 1
  • 1
Preetam Kumar
  • 436
  • 2
  • 19
  • The XML `Validator` tests a given document against a specified schema. Such a validation is unnecessary here, because the OP is asking for parsing the given string to check if the given string is either JSON or XML, simply speaking just make simple token parsing. – Lyubomyr Shaydariv Apr 13 '17 at 17:47
  • Thanks for your answer. In my case `XmlSourceFile` is a string, so I would replace `XmlSourceFile` with `new InputSource(new StringReader(XmlSourceFile)`. – 6324 Apr 13 '17 at 18:22
  • 1
    You can parse string via InputStream. `dBuilder.parse(new ByteArrayInputStream(strXML.getBytes("UTF-8")));` – Avec Sep 27 '18 at 12:49
4

youre right in that to really see if something is json or xml you must try and parse it as such - there's no "flat string" solution to this (see very famous related question here)

the only area of improvement i could think of here is in performance of the parsing:

  1. it appears youre using a json parser that produces a DOM tree. that means that you end up with an object tree in memory representing the json, when all you wanted was to see if its valid json or not. using streaming json (see here) you could get the same results with a lower memory overhead (no tree actually created)
  2. i dont know what parseXML does but it likely suffers the same issue as above
Community
  • 1
  • 1
radai
  • 23,949
  • 10
  • 71
  • 115
  • Thanks for your answer. I just tried with JSON and XML streams. It looks like that JSON stream parser will recognize invalid JSON/XML as JSON, and XML stream parser will recognize invalid JSON/XML as XML. So there are problems when I use the two stream parsers together. My current solution works though. But you have pointed out the key points which I did not know. This might help me in the future. – 6324 Apr 13 '17 at 18:20
  • @Yilong - there are multiple streaming xml and json parsers, and each with their own configuration options. i would be surprised if none of them could be configured to be more strict and emit error events/exceptions, but i've never had to do this myself so im not certain. – radai Apr 13 '17 at 18:44
-1

here's how i would do it ..

To validate if a string is JSON

    //isValidJson = false;
    /*try 
    {
    Gson gs = new Gson();
    Object ob = gs.ToJson(yourStringToValidate)
    isValidJson = true;
    }
    catch  
    {
    //do nothing
    }

    isValidXML = false;
    /*try 
    {
    //using JAXB try converting to a Java object
    JAXBContext jaxbContext = JAXBContext.newInstance(Object.class);
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            Object obj = (Object) unmarshaller.unmarshal(YourString/Fileobj);

    isValidXML = true;
    }
    catch  
    {
    //do nothing
    }