Comments (2)
My semi-systematic experimentation suggests that the observed field order will be:
- all non-
Option
fields, in declaration order (relative to one another); then - all
Option
fields, in declaration order (relative to one another)
By declaration order, I mean the same order as productElementNames
.
So if either all fields are Option
s or zero fields are Option
s, the existing code will do the right thing.
Here's a blueprint for a workaround:
def workaround[T <: Product](w: OWrites[T]): OWrites[T] = {
OWrites.transform(w) { case (product, misorderedObject) =>
val pairs = misorderedObject.value
JsObject(
product.productElementNames
.map(key => pairs.get(key).map(key -> _))
.collect { case Some(pair) => pair }
.toSeq
)
}
}
implicit val writes: OWrites[Foo] = workaround(Json.writes[Foo])
This can be simplified—you can use apply instead of get and then remove the collect—if all fields are always present in the output, e.g. if you use JsonConfiguration(optionHandlers = OptionHandlers.WritesNull)
in a relatively simple context.
It is of note that the bug seems to still occur if all fields are present in the output—so it must depend on the optionality in the declaration, not in the output.
In version 3.0.3 I did some jump-to-source maneuvers in my application:
- OptionHandlers.WritesNull.writeHandler refers to
- JsPath.writeOptionWithNull which refers to
- Writes.at, which is really PathWrites.at, which refers to
- JsPath.createObj, at https://github.com/playframework/play-json/blob/3.0.3/play-json/shared/src/main/scala/play/api/libs/json/JsPath.scala#L133, which has a note saying "// TODO implement it correctly (doesn't merge )"
That sounds suspicious, but it's no smoking gun. I dug around some more, and found this:
- A list of fields is separated by whether they are optional or not:
- Data derived from this partition are concatenated here:
This looks like the cause of exactly the pattern I have observed, i.e. a smoking gun.
Across my work I think I have only seen the bug in those projects that use Scala 3. This makes sense, the apparent smoking gun is in a scala3-specific folder, so one would expect the bug to occur if and only if using Scala 3. This matches what @levinson wrote in the issue-creating post: "TODO: Test fails when using Scala 3".
I hope this helps.
from play-json.
Happens here as well.
Having for example this class:
object MetricStatistics{
implicit val format: Format[MetricStatistics] = Json.format[MetricStatistics]
}
case class MetricStatistics(from: Instant, to: Instant, min: Option[Double], max: Option[Double], average: Option[Double], count: Long, centroid: Option[GeoLocation])
In scala 2.13, generated json was according to field order, but after upgrading to Scala 3, this is the order of an example:
{
"count": 6,
"min": 10.3,
"to": "2010-06-24T09:55:00Z",
"max": 100,
"from": "1980-06-24T05:55:00Z",
"centroid": {
"lat": 0,
"lon": 0
},
"average": 38.926
}
It breaks a lot of tests we have :(
Is there a fix in the plan?
from play-json.
Related Issues (20)
- add hook to allow play-json users to provide their own Jackson JsonFactory or ObjectMapper
- Case Class AnyVal Not Working with Json.reads/Json.writes HOT 2
- Support Scala 3 Enums HOT 3
- compile error HOT 1
- Json.writes[myScala3Enum] crashes play-json / the compilation? HOT 1
- Constructing Writes fail to compile with Scala 3 HOT 1
- Json.parse fails for strings > 5000000 in length HOT 4
- new RC pubished for Scala 3.3.0 HOT 6
- java.io.NotSerializableException on play.api.libs.json.ImmutableLinkedHashMap HOT 6
- Please can the scala 3 lib include the scala 2 macros? HOT 16
- `LowPriorityKeyReads.readableKeyReads` should not exist
- Difference between scala 3.3.1 and 2.13.12 when case class constructor is overridden with apply HOT 5
- "Exception occurred while executing macro expansion." HOT 2
- Add support for type constructors in macros for scala 3 HOT 3
- Generating a format for a sealed trait return compiler warning HOT 1
- Scala 3 macro cannot find Writes for Seq[Map[String, T]] HOT 1
- As a library user I want to configure the maximum size of deserialized JSONs HOT 1
- Exception is thrown when using Reads.DefaultInstantReads with an invalid Instant form HOT 1
- possible perf issues if you upgrade to Jackson 2.17
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from play-json.