Live data from Hacker News

JEP 540: Simple JSON API (Now in Incubator)

openjdk.org

71–80 of 83 posts

Re: JEP 540: Simple JSON API (Now in Incubator)

#71

Earlier quoted context omitted.

My understanding from reading this is the complete opposite. This library is explicitly not supporting the features that web servers need to be performant and handle production traffic, like streaming. A web server using this could only start parsing when it receives the last byte, and could only start responding when it’s done serializing, all while holding non-lazy trees of JsonValue objects in memory.

I've never built or worked on a service where the JSON payloads were so large that (de)serialization accounted for a significant portion of the timing profile I'm sure lots of them exist, but for your typical CRUD API, this has not been a phenomena I've run into.

I don’t have any benchmarks, but it’s surprisingly relevant. Not necessarily because parsing JSON is slow, but because managing memory is slow, and you’re dealing with potentially malicious input.

A non-streaming implementation needs to copy the request from the network stack into a contiguous GC-managed char array, possibly resizing it a few times as the data is received. Then when it’s time to parse, it goes through this array and allocates an unbounded number of JsonValue nodes. For JsonString and JsonNumber, it probably needs to create defensive copies of the data instead of spans of the input array, otherwise changing the input array corrupts the tree.

That’s kinda bad under memory pressure even for benign inputs. But consider malicious inputs, such as {"x":{"x":{"x":{"x":{"x":{…}}}}}. It would make this non-streaming implementation allocate a lot of String and JsonObject instances. The allocations would total multiple times the size of the input, and would be extremely fragmented.

On the other hand, a library that does streaming and that binds to objects could parse straight from the buffers in the network stack, and could avoid allocating objects for anything that it will not need to bind.

Re: JEP 540: Simple JSON API (Now in Incubator)

#72
post #39

Earlier quoted context omitted.

Currently, JsonObject.of has this signature: static JsonObject of(Map map); java.lang.String and other types don't extend JsonValue, and java lacks any trait-like way to add this functionality to existing types, so you would have to change the signature to this: static JsonObject of(Map map); Now you can pass any Object in, but the typechecker can't ensure that it is convertible to json anymore. I.e. it will have to…

A Modest Proposal that will never be implemented: add an interface to String, Boolean, Integer, Long, Float and Double. Because all these types already implement "toString" (and I believe their toString representations are compatible with JSON), it can be a pure marker interface.

> I believe their toString representations are compatible with JSON

Not quite. String is the big problem, since it needs to be wrapped in quotes, and special characters need to be escaped. But Float and Double are also problematic because Infinity and NaN aren't representable in json.

However, the new interface could have a "toJsonString" or maybe even a toJson method that returns a JsonValue

Re: JEP 540: Simple JSON API (Now in Incubator)

#73
post #30

Earlier quoted context omitted.

I'm not involved with the design of this API, but it seems to me that the issue on the JSON generation side (where you're complaining about ceremony) is feature creep. Creating the API you want on top of the proposed one is trivial (even in user code), but then where do you stop? If you have that conversion, it seems reasonable to also support, say, sets and records; maybe even enums. Indeed, Java JSON libraries typi…

Where to stop is a pretty fuzzy question I suppose. In my world, I think the worst possible outcome would be a java.util.json library that does 50-95% of what I currently do with GSON or Jackson. In that scenario I still need an external dependency, and I can either ignore java.util.json or turn a codebase into an error-prone mix of both. Maybe a good set of design considerations for java.util.json would be “what doe…

> Maybe a good set of design considerations for java.util.json would be “what does this API need to run a CRUD app written in modern java?”

Reading the JEP, that is not the motivation. The target is more a short script or some REPL interaction that reads JSON data from a web service and does something with it. A CRUD app likely already uses a web framework that comes with a full JSON library.

Re: JEP 540: Simple JSON API (Now in Incubator)

#74
post #48

Earlier quoted context omitted.

You really can't appreciate how awesome Clojure is until you're coming from Java, can you...

And vice versa. As someone who likes both languages, I appreciate how they both have their pros and cons. I was a Schemer before I learnt Java (when Java barely existed) and I adore Clojure, but if I were to write 10 MLOC mobile network routing and billing system, an air-traffic control system, or a credit-card transaction processing system etc. etc. that needs to evolve by a large team for 20 years, I would choose J…

For the systems you mentioned I’d choose Erlang or Elixir over Java or Closure. The right runtime for the right problems.

Re: JEP 540: Simple JSON API (Now in Incubator)

#75

Earlier quoted context omitted.

There's a nice Java library called Clojure with a lightweight syntax if you need to work with data structures and concurrency in Java a lot: (println (json/generate-string {:providers ["SUN" "SunRsaSign" "SunEC"]}))

I prefer its sibling library Kotlin, from the makers of the world famous Java IDE: Jetbrains Fleet

Unfortunately that library requires paying tribute to its owners, only made relevant thanks to shipping in phones powered by a green droid.

"The next thing is also fairly straightforward: we expect Kotlin to drive the sales of IntelliJ IDEA. We’re working on a new language, but we do not plan to replace the entire ecosystem of libraries that have been built for the JVM. So you’re likely to keep using Spring and Hibernate, or other similar frameworks, in your projects built with Kotlin. And while the development tools for Kotlin itself are going to be free and open-source, the support for the enterprise development frameworks and tools will remain part of IntelliJ IDEA Ultimate, the commercial version of the IDE. And of course the framework support will be fully integrated with Kotlin."

https://blog.jetbrains.com/kotlin/2011/08/why-jetbrains-need...

Re: JEP 540: Simple JSON API (Now in Incubator)

#76
post #34

I don't like this: String body = ... REST response body, which is a JSON document ... ; JsonValue json = Json.parse(body); json.get("properties").get("periods").asList().stream() .mapToInt(j -> j.get("temperature").asInt()) .average() .ifPresent(IO::println); Why am I able to call `.get(string)` or `.get(int)` on a JsonValue? Shouldn't these be on the JsonObject and JsonArray instead? > If the JsonValue instance is o…

The alternative has bad ergonomics, chained `.get`s which are the most common operation become:

   json.asObject().get("prop1").asObject().get("prop2")...

Re: JEP 540: Simple JSON API (Now in Incubator)

#77

A stated goal of the API is to have "low ceremony"; this seems like a lot of ceremony. IO.println(JsonObject.of(Map.of("providers", JsonArray.of(List.of(JsonString.of("SUN"), JsonString.of("SunRsaSign"), JsonString.of("SunEC")))))); There's gotta be a better way! Surely there could be some way of creating a JsonArray of native Java Strings, Booleans, Doubles, and Integers without requiring clients to explicitly conve…

I really wish the JDK devs would start using constructors again. I understand why factory methods exist but everything these days is of/from/newInstance/something else. Dart/Scala/Kotlin have all really solved this with language features and construction is uniform. For example in Dart they have factory constructors: https://dart.dev/language/constructors#factory-constructors

Re: JEP 540: Simple JSON API (Now in Incubator)

#78

Earlier quoted context omitted.

There's a nice Java library called Clojure with a lightweight syntax if you need to work with data structures and concurrency in Java a lot: (println (json/generate-string {:providers ["SUN" "SunRsaSign" "SunEC"]}))

I prefer its sibling library Kotlin, from the makers of the world famous Java IDE: Jetbrains Fleet

Isn’t json processing still a dependency in Kotlin? I love the language but I don’t think it’s equivalent to built in json processing.

Re: JEP 540: Simple JSON API (Now in Incubator)

#79
post #51

Earlier quoted context omitted.

POJOs and records require more configuration (e.g. Jackson's @JsonProperty, @JsonDeserialize). That could plausibly be out of scope. But for constructing JSON out of strings, numbers, booleans, lists, and maps, there's really not that much scope to creep into. Specifically, I think it would be perfectly cromulent to have JsonArray.of() be able to support any Iterable of native Strings, Integers, Doubles, or Booleans;…

> there's really not that much scope to creep into First, we've been in this game far too long to know that this isn't the case. Second, this is only incubation. It may well be that the team behind this feature intend to add more convenience methods but wish to do it later once the core is more battle-tested. It's always best to focus on the core first and add ornamentation once you know the core is right.

Shouldn't the core provided by this JEP be a streaming API then, so that you can build whatever you need on top of it? But they specifically exclude that from the goals.

Re: JEP 540: Simple JSON API (Now in Incubator)

#80
post #39

A stated goal of the API is to have "low ceremony"; this seems like a lot of ceremony. IO.println(JsonObject.of(Map.of("providers", JsonArray.of(List.of(JsonString.of("SUN"), JsonString.of("SunRsaSign"), JsonString.of("SunEC")))))); There's gotta be a better way! Surely there could be some way of creating a JsonArray of native Java Strings, Booleans, Doubles, and Integers without requiring clients to explicitly conve…

Currently, JsonObject.of has this signature: static JsonObject of(Map map); java.lang.String and other types don't extend JsonValue, and java lacks any trait-like way to add this functionality to existing types, so you would have to change the signature to this: static JsonObject of(Map map); Now you can pass any Object in, but the typechecker can't ensure that it is convertible to json anymore. I.e. it will have to…

> java.lang.String and other types don't extend JsonValue

And that ladies and gentlemen is what Java's re-doing of TypeClasses (called "witness" in the experiments they're doing now) are for.

Post reply on HN