@gmethvin and @jrudolph - There are a number of choices for how to represent JSON which are not entirely arbitrary, and by leaving an API without implementation, the consumer of the API cannot have any confidence about e.g. performance. Thus, having a common structure with implementation is a considerable addition of value to consumers (not producers) of JSON ASTs. Having to use reflection to inspect whether maybe you actually got the slow or non-compliant or whatever version from Group X is not very much fun.
So I don't think implementing API only is workable. One could leave out
unsafe and just say: the
safe API is the real one, and it's your job to get it there. On the other hand, the
unsafe API was built with careful attention to what you actually need during JSON parsing, without assuming things that may simply not be true. For example, JSON objects may (though it is not recommended) have multiple values for the same key. It's very easy to decide that JSON object representation is going to be map only, and then the AST is permanently unable to represent entirely valid JSON.
I think if you look through carefully, you'll find that the normal AST covers the common use cases quite well, and
unsafe covers the possible use cases quite well. As someone who might like to write stuff downstream from the API, that's as much as I want to have to think about. I don't want to have to worry that play-json and spray-json might secretly have different behavior once I've gotten a supposedly common API for them.
So I know as maintainers of libraries that produce JSON ASTs, it seems like a pain to have to use just one, but if you don't, I don't know why I as a consumer would care about a common AST at all.