KotestでJSON Schemaを検証する方法

shouldEqualJson だと、検証に含めたくない keyがある場合に使用できない。
shouldEqualSpecifiedJson だと、何かしらの不具合や改修でjsonのプロパティが増えた場合にエラーにならない。
そのような場合に、shouldEqualSpecifiedJson + JSONのSchemaの検証で対応できます。

# JSON Schemaを検証する方法
shouldMatchSchema を使用します。
公式ドキュメントは以下になります。
https://kotest.io/docs/assertions/json/json-overview.html

```kotlin
import io.kotest.assertions.json.schema.*
import io.kotest.core.spec.style.FreeSpec

class JsonSchemaTest : FreeSpec({
    this as JsonSchemaTest
    
    "ユーザプロフィールのJSON Schemaが正しいこと" {
        val jsonValue = """
            {
                "userId":1,
                "name":"山田太郎",
                "profile":{
                    "nickname":"ヤマダー",
                    "phone":"090-1111-2222"
                }
            }
        """.trimIndent()

        val userWithProfileJsonSchema = jsonSchema {
            obj {
                additionalProperties = false // 指定したプロパティ以外が存在する場合にエラーにする
                integer("userId")
                string("name")
                obj("profile") {
                    additionalProperties = false
                    string("nickname")
                    string("phone")
                }
            }
        }
        
        jsonValue shouldMatchSchema userWithProfileJsonSchema
    }
})
```

# 一部のSchemaを共通化する方法
以下のような2つの形式のJSONがあります。
```json
{
	"userId": 1,
	"name": "山田太郎",
	"profile": {
		"nickname": "ヤマダー",
		"phone": "090-1111-2222"
	}
}
```
```json
{
	"userId": 1,
	"name": "山田太郎",
	"hobby": {
		"sports": "baseball"
	}
}
```
その場合に、userId、nameのSchemaを共通化する方法です。
`JsonSchema.JsonObjectBuilder`の拡張関数を作成することで可能です。
```kotlin
import io.kotest.assertions.json.schema.*
import io.kotest.core.spec.style.FreeSpec

class JsonSchemaTest : FreeSpec({
    this as JsonSchemaTest

    "ユーザプロフィールのjson schemaが正しいこと" {
        val jsonValue = """
            {
                "userId":1,
                "name":"山田太郎",
                "profile":{
                    "nickname":"ヤマダー",
                    "phone":"090-1111-2222"
                }
            }
        """.trimIndent()

        val userWithProfileJsonSchema = jsonSchema {
            obj {
                additionalProperties = false
                basicInfo() // 共通化した拡張関数を呼ぶ
                obj("profile") {
                    additionalProperties = false
                    string("nickname")
                    string("phone")
                }
            }
        }

        jsonValue shouldMatchSchema userWithProfileJsonSchema
    }

    "ユーザ趣味のjson schemaが正しいこと" {
        val jsonValue = """
            {
                "userId":1,
                "name":"山田太郎",
                "hobby":{
                    "sports":"baseball"
                }
            }
        """.trimIndent()

        val userWithHobbyJsonSchema = jsonSchema {
            obj {
                additionalProperties = false
                basicInfo()
                obj("hobby") {
                    additionalProperties = false
                    string("sports")
                }
            }
        }

        jsonValue shouldMatchSchema userWithHobbyJsonSchema
    }
}) {
    fun JsonSchema.JsonObjectBuilder.basicInfo() {
        integer("userId")
        string("name")
    }
}
```