4

I have a byte[] that represents a UTF-8-encoded YAML string and I want to deserialize it. Here's the generic method I'm using:

public static <T> T getInstanceFromBinary(final Class<T> clazz, final byte[] binary, final String encoding)
        throws IOException {
    final StringReader stringReader = new StringReader(new String(binary, encoding));
    final String yamlString = stringReader.toString();
    final boolean hasTab = yamlString.contains("\t");
    final YamlReader reader = new YamlReader(stringReader);
    final T clazzInstance = reader.read(clazz);
    reader.close();
    return clazzInstance;
}

and I'm getting this exception:

Caused by: com.esotericsoftware.yamlbeans.tokenizer.Tokenizer$TokenizerException: Line 185, column 35: Tabs cannot be used for indentation.
    at com.esotericsoftware.yamlbeans.tokenizer.Tokenizer.fetchMoreTokens(Tokenizer.java:313)
    at com.esotericsoftware.yamlbeans.tokenizer.Tokenizer.peekNextToken(Tokenizer.java:120)
    at com.esotericsoftware.yamlbeans.tokenizer.Tokenizer.peekNextTokenType(Tokenizer.java:125)
    at com.esotericsoftware.yamlbeans.parser.Parser$20.produce(Parser.java:320)
    at com.esotericsoftware.yamlbeans.parser.Parser.getNextEvent(Parser.java:80)
    at com.esotericsoftware.yamlbeans.parser.Parser.peekNextEvent(Parser.java:91)
    at com.esotericsoftware.yamlbeans.YamlReader.readValueInternal(YamlReader.java:270)
    at com.esotericsoftware.yamlbeans.YamlReader.readValue(YamlReader.java:152)
    at com.esotericsoftware.yamlbeans.YamlReader.readValueInternal(YamlReader.java:295)
    ... 38 more

The problem is that the decoded string doesn't seem to contain a tab character. Here's a screenshot from the debug that confirms this:

Debug info

I've also checked YAMLBeans source code, and found where this exception is thrown, although this didn't yield any light about why this is happening or how to solve this issue.

Thanks in advance for any insights.

m0skit0
  • 25,268
  • 11
  • 79
  • 127

1 Answers1

3

You are calling toString() on your StringReader which returns the cryptic and rather useless implementation provided by Object.toString(). java.io.StringReader@329dbdbf i.e. it doesn't tell you if you have tabs or not.

Instead you need to check the original String you used before passing it to StringReader and possibly apply .replaceAll("\t", "\\t")

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • `StringReader#toString()` actually returns the YAML string just like `StringBuffer` (which is what `StringReader` uses internally IIRC). – m0skit0 Dec 14 '15 at 17:09
  • 1
    @m0skit0: Your debug screenshot says otherwise. StringBuilder and StringBuffer both return the backed string, but StringReader does not. See also https://stackoverflow.com/questions/17751056/how-do-i-convert-a-stringreader-to-a-string – Michael Myers Dec 14 '15 at 17:11
  • @m0skit0 not in the version of Java I have nor the version of Java you have according to your debugger. Are you saying `java.io.StringReader@329dbdbf` is your YAML? – Peter Lawrey Dec 14 '15 at 17:11
  • @m0skit0 https://docs.oracle.com/javase/8/docs/api/java/io/StringReader.html states that toString() is inherited from Object. – Peter Lawrey Dec 14 '15 at 17:12
  • @m0skit0 Peter is right mate, I just checked it too – nafas Dec 14 '15 at 17:14
  • 1
    Oh damn, sorry, yes, you're totally right. Too many hours with this has fried my brain. I have the extracted the YAML string so I thought I got it from there. And yes, the string does contain tabs, which leads me to the new problem on why it has them... Thanks for your help! – m0skit0 Dec 14 '15 at 17:16
  • 1
    The actual issue was that one piece of data had a tab character on it. Removing it worked just fine. – m0skit0 Dec 14 '15 at 18:04