scala-jsonschema icon indicating copy to clipboard operation
scala-jsonschema copied to clipboard

The json schema dereviation does not account JsonNaming config of specific bridge

Open limpid-kzonix opened this issue 3 years ago • 3 comments

It seems that the library does not provide the capability to treat the configuration of the play-json JsonNaming or Configuration.default.withSnakeCaseMemberNames to the schema dereviation.

To Reproduce Code describing your situation

import io.circe.generic.extras.ConfiguredJsonCodec
import io.circe.generic.extras._

@ConfiguredJsonCodec
case class Data(
    fieldName1: String,
    fieldName2: String,
    itMustBeVeryLongFieldName1: String
)

object Data {

  implicit val configuration: Configuration =
    Configuration.default.withSnakeCaseMemberNames
}
import play.api.libs.json._
import play.api.libs.json.JsonNaming.SnakeCase
import play.api.libs.json.JsonConfiguration.Aux
import com.github.andyglow.jsonschema.AsPlay._
import json.schema.Version.Draft07
import json.{Json => JsonSchema}

object PlayExample {

  implicit val config: Aux[Json.MacroOptions] = JsonConfiguration(SnakeCase)

  implicit val dataReads: Reads[Data] = Json.reads[Data]
  implicit val dataWrites: Writes[Data] = Json.writes[Data]

  val dataObject: String =
    Json.prettyPrint(
      Json.toJson(Data("some value 1", "some value 2", "some value 3"))
    )
  val schema: String =
    Json.prettyPrint(JsonSchema.schema[Data].asPlay(Draft07("/schemas/data")))

}
import com.github.andyglow.jsonschema.AsCirce._
import json.{Json => JsonSchema}
import io.circe.syntax._
import json.schema.Version.Draft07

object CirceExample {

  val dataObject: String =
    Data("some value 1", "some value 2", "some value 3").asJson.spaces2

  val schema: String =
    JsonSchema.schema[Data].asCirce(Draft07("/schemas/data")).spaces4

}

Expected behavior The filed naming in the generated json schema should reflect the field naming of the actual encoded object

Actual results Inconsistently resulted schema:

Circe Example

Generated json schema:

{
    "$id" : "/schemas/data",
    "properties" : {
        "fieldName1" : {
            "type" : "string"
        },
        "fieldName2" : {
            "type" : "string"
        },
        "itMustBeVeryLongFieldName1" : {
            "type" : "string"
        }
    },
    "additionalProperties" : false,
    "$schema" : "http://json-schema.org/draft-07/schema#",
    "type" : "object",
    "required" : [
        "fieldName1",
        "fieldName2",
        "itMustBeVeryLongFieldName1"
    ]
}

Encoded object result

{
  "field_name1" : "some value 1",
  "field_name2" : "some value 2",
  "it_must_be_very_long_field_name1" : "some value 3"
}

PlayJson example

Generated json schema:

{
  "$id" : "/schemas/data",
  "properties" : {
    "fieldName1" : {
      "type" : "string"
    },
    "fieldName2" : {
      "type" : "string"
    },
    "itMustBeVeryLongFieldName1" : {
      "type" : "string"
    }
  },
  "additionalProperties" : false,
  "$schema" : "http://json-schema.org/draft-07/schema#",
  "type" : "object",
  "required" : [ "fieldName1", "fieldName2", "itMustBeVeryLongFieldName1" ]
}

Encoded object result

{
  "field_name1" : "some value 1",
  "field_name2" : "some value 2",
  "it_must_be_very_long_field_name1" : "some value 3"
}

Versions:

  • jsonschema version = "0.7.8"
  • scala version = "2.13"

Additional context Add any other context about the problem here. https://github.com/oleksandr-balyshyn/scala-json-schema-example

limpid-kzonix avatar Jul 05 '22 00:07 limpid-kzonix

Thanks @andyglow for your contribution to the scala community by providing such useful library. I have been using it for a while and just recently noticed this incosistency in naming. It would be very much appreciated, if can point me to the places from which I can start research for further providing of the PR.

limpid-kzonix avatar Jul 05 '22 00:07 limpid-kzonix

The potential solution can look similar to Tapir Schema Deriviation e.g to have custom Config class that can describe the Json naming policy.

import sttp.tapir.generic.Configuration

implicit val customConfiguration: Configuration =
  Configuration.default.withSnakeCaseMemberNames

limpid-kzonix avatar Jul 05 '22 00:07 limpid-kzonix

Hello, @limpid-kzonix Thank you for such a detailed description of the problem Yeah.. I know about the problem existence.. There is an issue aimed to introduce the general solution to all the problems of this kind (link #88)

The idea is to either allow the developer to describe the need or to infer the lib-specific bits like those annotations, critical typeclasses available in the scope, etc and from that to build the model of the necessary changes that needs to be applied to the schema model before it can be rendered

Unfortunately I have no time now to dive into it.. So if you are available to contribute it would be more then welcomed!

andyglow avatar Jul 05 '22 18:07 andyglow