Make subsonic error parser more fail safe.

Now it should parse more malformed error json, though having "code" field is still mandatory.

Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
This commit is contained in:
Yahor Berdnikau 2018-01-20 10:56:58 +01:00
parent b38f4894c3
commit 0b5cc5d3f3
6 changed files with 91 additions and 7 deletions

View File

@ -113,6 +113,42 @@ class SubsonicApiErrorsTest : SubsonicAPIClientTest() {
response.assertError(RequestedDataWasNotFound)
}
@Test
fun `Should parse error with reversed tokens order`() {
mockWebServerRule.enqueueResponse("reversed_tokens_generic_error.json")
val response = client.api.ping().execute()
response.assertError(Generic("Video streaming not supported"))
}
@Test
fun `Should parse error if json contains error first before other fields`() {
mockWebServerRule.enqueueResponse("error_first_generic_error.json")
val response = client.api.ping().execute()
response.assertError(Generic("Video streaming not supported"))
}
@Test
fun `Should parse error if json doesn't contain message field`() {
mockWebServerRule.enqueueResponse("without_message_generic_error.json")
val response = client.api.ping().execute()
response.assertError(Generic(""))
}
@Test
fun `Should parse error if error json contains additional object`() {
mockWebServerRule.enqueueResponse("with_additional_json_object_generic_error.json")
val response = client.api.ping().execute()
response.assertError(Generic(""))
}
private fun Response<SubsonicResponse>.assertError(expectedError: SubsonicError) =
with(body()) {
error `should not be` null

View File

@ -0,0 +1,10 @@
{
"subsonic-response": {
"error": {
"message": "Video streaming not supported",
"code": 0
},
"version": "1.8.0",
"status": "failed"
}
}

View File

@ -0,0 +1,10 @@
{
"subsonic-response": {
"status": "failed",
"version": "1.8.0",
"error": {
"message": "Video streaming not supported",
"code": 0
}
}
}

View File

@ -0,0 +1,13 @@
{
"subsonic-response": {
"status": "failed",
"version": "1.8.0",
"error": {
"code": 0,
"unicorn" : {
"code": 41,
"message": "Unicorns doesn't exist!"
}
}
}
}

View File

@ -0,0 +1,9 @@
{
"subsonic-response": {
"status": "failed",
"version": "1.8.0",
"error": {
"code": 0
}
}
}

View File

@ -1,6 +1,8 @@
package org.moire.ultrasonic.api.subsonic
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken.END_OBJECT
import com.fasterxml.jackson.core.JsonToken.START_OBJECT
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
@ -36,13 +38,17 @@ sealed class SubsonicError(val code: Int) {
class SubsonicErrorDeserializer : JsonDeserializer<SubsonicError>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): SubsonicError {
p.nextToken() // { -> "code"
p.nextToken() // "code" -> codeValue
val code = p.valueAsInt
p.nextToken() // codeValue -> "message"
p.nextToken() // "message" -> messageValue
val message = p.text
p.nextToken() // value -> }
var code = -1
var message = ""
while (p.nextToken() != END_OBJECT) {
when {
p.currentToken == START_OBJECT -> p.skipChildren()
"code".equals(p.currentName, ignoreCase = true) ->
code = p.nextIntValue(-1)
"message".equals(p.currentName, ignoreCase = true) ->
message = p.nextTextValue()
}
}
return getError(code, message)
}
}