Add support of oneOf(primitive|object) in the json parser generator#2972
Conversation
|
🎯 Code Coverage 🔗 Commit SHA: 1585433 | Docs | Datadog PR Page | Was this helpful? Give us feedback! |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #2972 +/- ##
===========================================
- Coverage 70.91% 70.84% -0.07%
===========================================
Files 829 829
Lines 30381 30381
Branches 5184 5184
===========================================
- Hits 21543 21522 -21
- Misses 7373 7385 +12
- Partials 1465 1474 +9 🚀 New features to boost your workflow:
|
5bac644 to
dd8cc53
Compare
dd8cc53 to
67dcf0d
Compare
|
|
||
| @JvmStatic | ||
| @Throws(JsonParseException::class) | ||
| public fun fromJsonObject(jsonElement: JsonElement): Path { |
There was a problem hiding this comment.
The json element corresponding to oneOf now is either JsonObject or JsonPrimitive. Their common parent is JsonElement.
| null | ||
| } | ||
| val asBoolean = try { | ||
| if (jsonElement is JsonPrimitive) { |
There was a problem hiding this comment.
First checking jsonElement is JsonPrimitive, then trying to parse a Boolean
| null | ||
| } | ||
| val asPoint = try { | ||
| if (jsonElement is JsonObject) { |
There was a problem hiding this comment.
First checking jsonElement is JsonObject, then trying to parse a Point
| data class OneOfClass( | ||
| val name: String, | ||
| val options: List<Class>, | ||
| val options: List<Option>, |
There was a problem hiding this comment.
Now options of oneOf can be either a class or a primitive.
| import com.squareup.kotlinpoet.TypeSpec | ||
| import com.squareup.kotlinpoet.jvm.throws | ||
|
|
||
| class OneOfPrimitiveOptionGenerator( |
There was a problem hiding this comment.
This class is responsible for generating code of primitive options of oneOf. It is used in MultiClassGenerator.
Code for class options of oneOf is generated in MultiClassGenerator as before.
| @Throws(JsonParseException::class) | ||
| public fun fromJsonObject(jsonObject: JsonPrimitive): String { | ||
| try { | ||
| if (jsonObject.isString) { |
There was a problem hiding this comment.
This isString check is important. Otherwise is jsonObject contains Int or Boolean jsonObject.asString will successfully "parse" it. This isn't what we want.
| @Throws(JsonParseException::class) | ||
| public fun fromJsonObject(jsonObject: JsonPrimitive): Boolean { | ||
| try { | ||
| if (jsonObject.isBoolean) { |
There was a problem hiding this comment.
This isBoolean check is important. Otherwise .asBoolean it will try doing this.
| @Throws(JsonParseException::class) | ||
| public fun fromJsonObject(jsonObject: JsonPrimitive): Long { | ||
| try { | ||
| if (jsonObject.isNumber) { |
There was a problem hiding this comment.
This isNumber check is important. Otherwise .asLong will try to extract a number from a string link.
| companion object | ||
| fun fromJson(kotlin.String): Vital | ||
| fun fromJsonObject(com.google.gson.JsonObject): Vital | ||
| fun fromJsonObject(com.google.gson.JsonElement): Vital |
There was a problem hiding this comment.
we probably need to rename fromJsonObject to fromJsonElement then, but such change will break Flutter, for example https://github.com/search?q=repo%3ADataDog%2Fdd-sdk-flutter%20fromJsonObject&type=code
There was a problem hiding this comment.
Good point.
I will try to rename, but I think we should rename fromJsonObject to fromJsonElement only in places where JsonElement is passed as an argument.
We can also rename here to fromJsonPrimitive (this file is introduced in the current PR).
but such change will break Flutter
LogEvent isn't affected by my change. It is still parsed from jsonObject, so no need to rename its method.
IIUC the usage in flutter that you mentioned is the only place where we use fromJsonObject link. So it should be safe to rename.
There was a problem hiding this comment.
renamed to fromJsonElement and fromJsonPrimitive where needed
| ClassNameRef.IllegalStateException, | ||
| ClassNameRef.UnsupportedOperationException | ||
| ) | ||
| JsonPrimitiveType.DOUBLE -> error("Double is not supported") |
There was a problem hiding this comment.
Actually, I can entirely remove JsonPrimitiveType.DOUBLE from the code.
It is never used, we don't assign it anywhere when we parse the json link.
And JSON Schema actually has only integer and number. https://json-schema.org/understanding-json-schema/reference/numeric
I don't know why JsonPrimitiveType.DOUBLE was introduced in the first place.
There was a problem hiding this comment.
removed JsonPrimitiveType.DOUBLE from the codebase
7cf8f4c
7cf8f4c to
1585433
Compare
| rootTypeName: String | ||
| ) { | ||
| val opt = if (nullable) "?" else "" | ||
| beginControlFlow("$assignee = $getter$opt.asJsonObject$opt.let") |
There was a problem hiding this comment.
This is an important place that I missed. It corresponds to the situation when a oneOf is a field of some object.
When we are deserializing a oneOf, we need to treat it as JsonElement now. But here it was cast to JsonObject and it failed if the option of oneOf was of primitive type.
My new tests only tested the case when oneOf(primitive) was an element of an array.
I modified an old test here to test this scenario.
| ClassNameRef.IllegalStateException, | ||
| ClassNameRef.UnsupportedOperationException | ||
| ) | ||
| JsonPrimitiveType.DOUBLE -> error("Double is not supported") |
There was a problem hiding this comment.
removed JsonPrimitiveType.DOUBLE from the codebase
| companion object | ||
| fun fromJson(kotlin.String): Vital | ||
| fun fromJsonObject(com.google.gson.JsonObject): Vital | ||
| fun fromJsonObject(com.google.gson.JsonElement): Vital |
There was a problem hiding this comment.
renamed to fromJsonElement and fromJsonPrimitive where needed
What does this PR do?
This PR addresses this issue.
It implements support for the following case:
Options of
oneOfcan also be of primitive types.The best way to look at this PR is to start with the changes in the unit tests of the generator and then to read the comments to the PR explaining specific places in code.
I will update RUM schema to the latest version in a separate PR.
Motivation
What inspired you to submit this pull request?
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)