package jp.juggler.subwaytooter import jp.juggler.util.data.buildJsonArray import jp.juggler.util.data.buildJsonObject import jp.juggler.util.data.decodeJsonObject import jp.juggler.util.data.decodeJsonValue import jp.juggler.util.data.isDecimalNotation import jp.juggler.util.data.jsonObjectOf import jp.juggler.util.data.writeJsonValue import java.io.StringWriter import kotlin.test.Test import kotlin.test.assertEquals class TestJson { companion object { private val epsilon = java.lang.Double.longBitsToDouble(971L shl 52) fun Any?.encodeSimpleJsonValue(indentFactor: Int): String { val sw = StringWriter() synchronized(sw.buffer) { return sw.writeJsonValue(indentFactor, 0, this, sort = true).toString() } } } @Suppress("unused") enum class En { Aa, Bb, Cc } @Test fun encode1() { assertEquals("null", null.encodeSimpleJsonValue(0)) assertEquals("true", true.encodeSimpleJsonValue(0)) assertEquals("false", false.encodeSimpleJsonValue(0)) assertEquals("0", 0.encodeSimpleJsonValue(0)) assertEquals("1", 1.encodeSimpleJsonValue(0)) assertEquals("-1", (-1).encodeSimpleJsonValue(0)) assertEquals("-2147483648", Int.MIN_VALUE.encodeSimpleJsonValue(0)) assertEquals("2147483647", Int.MAX_VALUE.encodeSimpleJsonValue(0)) assertEquals("0", 0L.encodeSimpleJsonValue(0)) assertEquals("1", 1L.encodeSimpleJsonValue(0)) assertEquals("-1", (-1L).encodeSimpleJsonValue(0)) assertEquals("-9223372036854775808", Long.MIN_VALUE.encodeSimpleJsonValue(0)) assertEquals("9223372036854775807", Long.MAX_VALUE.encodeSimpleJsonValue(0)) assertEquals("0", 0f.encodeSimpleJsonValue(0)) assertEquals("1", 1f.encodeSimpleJsonValue(0)) assertEquals("-1", (-1f).encodeSimpleJsonValue(0)) assertEquals("1.4E-45", Float.MIN_VALUE.encodeSimpleJsonValue(0)) assertEquals("3.4028235E38", Float.MAX_VALUE.encodeSimpleJsonValue(0)) assertEquals("0", 0.0.encodeSimpleJsonValue(0)) assertEquals("1", 1.0.encodeSimpleJsonValue(0)) assertEquals("-1", (-1.0).encodeSimpleJsonValue(0)) assertEquals("4.9E-324", Double.MIN_VALUE.encodeSimpleJsonValue(0)) assertEquals("1.7976931348623157E308", Double.MAX_VALUE.encodeSimpleJsonValue(0)) assertEquals("0", 0.toChar().encodeSimpleJsonValue(0)) assertEquals("1", 1.toChar().encodeSimpleJsonValue(0)) assertEquals("65535", (-1).toChar().encodeSimpleJsonValue(0)) assertEquals("0", Char.MIN_VALUE.encodeSimpleJsonValue(0)) assertEquals("65535", Char.MAX_VALUE.encodeSimpleJsonValue(0)) // 空文字列 assertEquals("\"\"", "".encodeSimpleJsonValue(0)) val escaped = ArrayList() // Unicode1文字(エスケープのテスト for (i in 0 until 0x10000) { val c = i.toChar() val raw = c.toString() val encoded = raw.encodeSimpleJsonValue(0) val decoded = encoded.decodeJsonValue() assertEquals(raw, decoded) if (encoded.length > 3) escaped.add(encoded.substring(1, encoded.length - 1)) } @Suppress("MaxLineLength") assertEquals( """\",\\,\b,\f,\n,\r,\t,\u0000,\u0001,\u0002,\u0003,\u0004,\u0005,\u0006,\u0007,\u000b,\u000e,\u000f,\u0010,\u0011,\u0012,\u0013,\u0014,\u0015,\u0016,\u0017,\u0018,\u0019,\u001a,\u001b,\u001c,\u001d,\u001e,\u001f,\u0080,\u0081,\u0082,\u0083,\u0084,\u0085,\u0086,\u0087,\u0088,\u0089,\u008a,\u008b,\u008c,\u008d,\u008e,\u008f,\u0090,\u0091,\u0092,\u0093,\u0094,\u0095,\u0096,\u0097,\u0098,\u0099,\u009a,\u009b,\u009c,\u009d,\u009e,\u009f,\u2000,\u2001,\u2002,\u2003,\u2004,\u2005,\u2006,\u2007,\u2008,\u2009,\u200a,\u200b,\u200c,\u200d,\u200e,\u200f,\u2010,\u2011,\u2012,\u2013,\u2014,\u2015,\u2016,\u2017,\u2018,\u2019,\u201a,\u201b,\u201c,\u201d,\u201e,\u201f,\u2020,\u2021,\u2022,\u2023,\u2024,\u2025,\u2026,\u2027,\u2028,\u2029,\u202a,\u202b,\u202c,\u202d,\u202e,\u202f,\u2030,\u2031,\u2032,\u2033,\u2034,\u2035,\u2036,\u2037,\u2038,\u2039,\u203a,\u203b,\u203c,\u203d,\u203e,\u203f,\u2040,\u2041,\u2042,\u2043,\u2044,\u2045,\u2046,\u2047,\u2048,\u2049,\u204a,\u204b,\u204c,\u204d,\u204e,\u204f,\u2050,\u2051,\u2052,\u2053,\u2054,\u2055,\u2056,\u2057,\u2058,\u2059,\u205a,\u205b,\u205c,\u205d,\u205e,\u205f,\u2060,\u2061,\u2062,\u2063,\u2064,\u2065,\u2066,\u2067,\u2068,\u2069,\u206a,\u206b,\u206c,\u206d,\u206e,\u206f,\u2070,\u2071,\u2072,\u2073,\u2074,\u2075,\u2076,\u2077,\u2078,\u2079,\u207a,\u207b,\u207c,\u207d,\u207e,\u207f,\u2080,\u2081,\u2082,\u2083,\u2084,\u2085,\u2086,\u2087,\u2088,\u2089,\u208a,\u208b,\u208c,\u208d,\u208e,\u208f,\u2090,\u2091,\u2092,\u2093,\u2094,\u2095,\u2096,\u2097,\u2098,\u2099,\u209a,\u209b,\u209c,\u209d,\u209e,\u209f,\u20a0,\u20a1,\u20a2,\u20a3,\u20a4,\u20a5,\u20a6,\u20a7,\u20a8,\u20a9,\u20aa,\u20ab,\u20ac,\u20ad,\u20ae,\u20af,\u20b0,\u20b1,\u20b2,\u20b3,\u20b4,\u20b5,\u20b6,\u20b7,\u20b8,\u20b9,\u20ba,\u20bb,\u20bc,\u20bd,\u20be,\u20bf,\u20c0,\u20c1,\u20c2,\u20c3,\u20c4,\u20c5,\u20c6,\u20c7,\u20c8,\u20c9,\u20ca,\u20cb,\u20cc,\u20cd,\u20ce,\u20cf,\u20d0,\u20d1,\u20d2,\u20d3,\u20d4,\u20d5,\u20d6,\u20d7,\u20d8,\u20d9,\u20da,\u20db,\u20dc,\u20dd,\u20de,\u20df,\u20e0,\u20e1,\u20e2,\u20e3,\u20e4,\u20e5,\u20e6,\u20e7,\u20e8,\u20e9,\u20ea,\u20eb,\u20ec,\u20ed,\u20ee,\u20ef,\u20f0,\u20f1,\u20f2,\u20f3,\u20f4,\u20f5,\u20f6,\u20f7,\u20f8,\u20f9,\u20fa,\u20fb,\u20fc,\u20fd,\u20fe,\u20ff""", escaped.sorted().joinToString(",") ) // enum assertEquals("\"Aa\"", En.Aa.encodeSimpleJsonValue(0)) // object val o = buildJsonObject {} assertEquals("{}", o.encodeSimpleJsonValue(0)) o["a"] = "b" assertEquals("{\"a\":\"b\"}", o.encodeSimpleJsonValue(0)) // Collection val a = buildJsonArray {} assertEquals("[]", a.encodeSimpleJsonValue(0)) a.add("b") assertEquals("[\"b\"]", a.encodeSimpleJsonValue(0)) a[0] = "c" assertEquals("[\"c\"]", a.encodeSimpleJsonValue(0)) } @Test fun testDecimalNotation() { fun x(expect: Boolean, n: Number) { val encoded = n.toString() val actual = encoded.isDecimalNotation() assertEquals( expected = expect, actual = actual, message = "${n.javaClass.simpleName} $n", ) } // integers and longs x(false, 0) x(false, -0) x(false, Int.MIN_VALUE) x(false, Int.MAX_VALUE) x(false, Long.MIN_VALUE) x(false, Long.MAX_VALUE) // floats x(true, 0f) // as "0.0" x(true, -0f) // as "-0.0" x(true, 0.5f) x(true, -0.5f) x(true, Float.MAX_VALUE) x(true, Float.MIN_VALUE) // doubles x(true, 0.0) // as "0.0" x(true, -0.0) // as "-0.0" x(true, 0.5) x(true, -0.5) x(true, Double.MAX_VALUE) x(true, Double.MIN_VALUE) x(true, epsilon) } @Test fun testNumberEncode() { fun x( n: Number, expectValue: Number = n, expectClass: Class<*> = expectValue.javaClass, ) { val encodedObject = jsonObjectOf("n" to n).toString() val decodedObject = encodedObject.decodeJsonObject() val decoded = decodedObject["n"] assertEquals?>( expected = expectClass, actual = decoded?.javaClass, message = "$n type $encodedObject", ) assertEquals( expected = expectValue, actual = decoded, message = "$n value $encodedObject", ) } x(0) x(0f, expectValue = 0) x(0.0, expectValue = 0) x(-0) x(-0f, expectValue = -0.0) x(-0.0) x(0.5f, expectValue = 0.5) x(0.5) x(-0.5f, expectValue = -0.5) x(-0.5) x(epsilon) x(Int.MIN_VALUE) x(Int.MAX_VALUE) x(Long.MIN_VALUE) x(Long.MAX_VALUE) x(Double.MAX_VALUE) x(Double.MIN_VALUE) // 誤差が出て上限/下限が合わないので、デコード時にはdouble解釈になる // x(Float.MAX_VALUE, expectValue = Float.MAX_VALUE.toDouble()) // x(Float.MIN_VALUE, expectValue = Float.MIN_VALUE.toDouble()) } }