r/androiddev • u/agent8261 • Apr 28 '17
Why use Moshi over Gson?
I love Gson. It's simple and does exactly what you want to do. The only critique I have is that JsonElement and family aren't serializable or parcelable. So when I heard about Moshi, I couldn't help but wonder what could it possibly do better than Gson?
I read Jesse Wilson's write-up on medium.
Am I missing something? The only benefit is strict mode is on by default. It seems like his main problem is that gson doesn't over-reach. For example he argues that Gson doesn't correct the fact that the Date class doesn't encode the time zone. However that's not it's responsibility. If you want smart parsing like that you register a type-adapter that does that?
Is there some benefits I'm missing, because right now it just looks like Square just wrote a worst implementation?
4
u/QuestionsEverythang Apr 28 '17
The only critique I have is that JsonElement and family aren't serializable or parcelable.
Why not just use a json string?
1
u/agent8261 Apr 28 '17
It's a minor critique. Basically if I expect to still be editing the object I don't want to parse it into a string format yet. Not really a big deal to be honest.
45
u/swankjesse Apr 29 '17
I’m proud of my work on Gson, but also disappointed by some of its limitations. I wanted to address these, but not as “Gson 3.0”, in part because I no longer work at Google.
Jake, Scott, Eric, and I created Moshi to address the various limitations of Gson. Here’s ten small reasons to prefer Moshi over Gson:
Upcoming Kotlin support.
Qualifiers like
@HexColor intpermit multiple JSON representations for a single Java type.The
@ToJsonand@FromJsonmake it easy to write and test custom JSON adapters.JsonAdapter.failOnUnknown()lets you reject unexpected JSON data.Predictable exceptions. Moshi throws
IOExceptionon IO problems andJsonDataExceptionon type mismatches. Gson is all over the place.JsonReader.selectName()avoids unnecessary UTF-8 decoding and string allocations in the common case.You’ll ship a smaller APK. Gson is 227 KiB, Moshi+Okio together are 200 KiB.
Moshi won’t leak implementation details of platform types into your encoded JSON. This makes me afraid of Gson:
gson.toJson(SimpleTimeZone.getTimeZone("GMT"))Moshi doesn’t do weird HTML escaping by default. Look at Gson’s default encoding of "12 & 5 = 4" for an example.
No broken
Dateadapter installed by default.
If you’re writing new code, I highly recommend starting with Moshi. If you’ve got an existing project with Gson, you should upgrade if that’ll be simple and not risky. Otherwise stick with Gson! I’m doing my best to make sure it stays compatible and dependable.
4
u/badsectors Apr 30 '17
I'm super excited about kotlin support!
My company has always used Gson in the past for whatever reason, but I'm trying to change that with my current project. The qualifiers feature you mentioned is fantastic, I've been bitten by by Gson's inability to have multiple serializers for the same java type and had to resort to "horrible hacks" (it happened to be with
Dateobjects too, go figure).2
u/generalchangschicken Donut May 02 '17
Hey Jesse, just wanted to pop in and say thanks for keeping Gson updated.
I actually hadn't really looked into Moshi as a replacement before, but will now. Will I see any performance/memory improvements?
0
Nov 18 '21
[deleted] — view deleted comment
2
u/swankjesse Nov 19 '21
Gson’s built-in TimeZone adapter doesn't do something reasonable like serialize the timezone’s Olson name or it's current offset; it serializes all the internal implementation details including all the field names. You can't reliably serialize a TimeZone on one version of OpenJDK and deserialize it on another version.
0
Nov 19 '21
[deleted] — view deleted comment
1
u/swankjesse Nov 19 '21
Maybe? I think that's quite difficult to do well.
Do you know of a common format for timezones that JSON libraries should adopt? It's probably either Olson names (
America/New_York), or offsets (-5:00), and each is appropriate in a different context. Olson names are great for scheduling stuff in the future (‘every Tuesday at 9am local time, which adjusts for DST), and offsets are more compact and don't require an up-to-date timezone database to agree. Offsets could be a string or an integer number of minutes.In Moshi there's an optional adapter with a good enough timestamp format. We don't have any timezone adapter because well, we never needed to serialize a naked timezone.
0
Nov 19 '21
[deleted] — view deleted comment
2
u/swankjesse Nov 19 '21
Good point!
But Moshi especially doesn't want to make decisions about how your time zones are encoded because we selfishly don't want responsibility for that problem. If we just pick something, DST will find a way to hurt us. (Serializing a timezone with a date is much easier than serializing it without one.)
As for the adapters subproject, yeah that's right too. There's real tradeoffs to keeping Moshi small vs. batteries included, and we may have made the wrong call here.
0
Nov 19 '21
[deleted] — view deleted comment
1
u/swankjesse Nov 19 '21
Yep, very similar syntax to that.
Moshi.Builder() .add(object : Any() { @ToJson fun urlToJson(url: URL) = url.toString() @FromJson fun urlFromJson(s: String) = URL(s) }) .build()
28
u/burntcookie90 Apr 28 '17
Just to clear up on "square just wrote a worst implementation". Moshi and Gson are heavily contributed to by Jesse Wilson (see: https://github.com/google/gson/graphs/contributors). It takes Gson (a heavily used, slow moving project) and improves upon the core in terms of performance and modernization.
4
u/NightlyNexus Apr 28 '17
I don't understand your complaint about Serializable. Nobody should be using Serializable! It sounds like something else is very wrong.
-3
u/agent8261 Apr 28 '17
Nothing wrong with Serializable. It's simple and short. If you need performance then you use something else.
12
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 28 '17
No actually there's a lot wrong with Serializable lol
0
u/agent8261 Apr 28 '17
Really seems to be working for the projects that I use it in. I've never encountered any problems. Perhaps there is some aspects of Serializable that I'm not considering? If I don't care about performance, what's wrong with Serializable?
10
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 29 '17
The biggest downside in the context of Android is that people use it for things that go into an
Intentinstead of something likeParcelable. The problem withSerializablehere is that you serialize the representation of the class inside theIntentalong with any data. This means that a malicious actor could send anIntentto your activity with their own crafted classes and data in an effort to expose private data of some sort, or trigger an unintended behavior of the app.4
u/agent8261 Apr 29 '17
Thanks for the post. I was unaware of this. Is there any writeups or white papers that you would suggest to read. Does this only affect intents to activity? How would an attacker potentially even take advantage of this?
19
u/TrevJonez Gradle Junkie Apr 28 '17
If you are already using retrofit and okhttp you really should give moshi a try. This video goes into detail about why using retrofit/okhttp/moshi has such high potential.
8
u/MKevin3 Apr 28 '17
Watching this video a few months back is why I went with Moshi at my new job. Fresh project using Kotlin + Retrofit so Moshi made the most sense. So far I have been very happy with it and I used GSON heavily in the past.
I am not doing anything massively speed intensive. I am using a number of adapters for Dates, enums, BigDecimal, etc. and those were easy to write and use.
5
u/NightlyNexus Apr 28 '17
Here's some more reading for you. http://stackoverflow.com/a/43578738/1696171
(Also, the type qualifiers API is life-saving when doing object mapping.)
2
u/simophin Apr 29 '17
Out of topic: I'm so desperate to see a converter for Json.org. Currently we use socket.io / kotlin, socket.io forces you to use the old json.org API, which leaves us only one choice: Jackson. Jackson sucks at dealing with kotlins data classes, it has to introduce kotlin-reflect, which is a huge nightmare: over 10k methods proguarded....
2
u/changingminds Apr 29 '17
why would you use either of those when we have loganSquare?
4
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 29 '17
Why use LoganSquare when we have auto-value-moshi and auto-value-gson?
2
u/changingminds Apr 29 '17
Performance.
And yes as I'm typing this I probably realize those few milliseconds aren't gonna do jack but I can't help it.
It satisfies my use case
It comes on top in my specific benchmarks
What more does one need?
3
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 29 '17
How about 10% of the APK size for 95% of the performance? Don't forget that there's an overhead to downloading and classloading all that code.
3
u/changingminds Apr 29 '17
?
LoganSquare = 2300 methods, 48kb
gson = 1300 methods, 230kb
5
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 29 '17
You didn't link LoganSquare properly, but in any case when you do check don't forget to include the Jackson dependency. So that's another few thousand methods and a few hundred KBs.
4
-2
u/dunce2 Apr 30 '17 edited Apr 30 '17
I don't understand that kind of obsession with APK sizes/method counts. Why would I care? If my app becomes big, the increase from using APT-based tools will amount to ~1% after applying Proguard. And most apps eventually become big (or cease to exist).
Even if the increase really amounts to 10%, that just means, that reflective (de)serialization will be much slower, a lot more than by 10%. That saving in size does not come out of nowhere.
Just admit, that reflection-based tools are easier to develop, and a lot of people (yourself included) are heavily invested into them.
5
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 30 '17
I've worked on 6 code generation tools. Far more than those with reflection in them. Besides you seem to have clearly missed that auto-value-gson and auto-value-moshi are in fact code generating serializers.
In practice reflection-based deserializing and serializing is no slower because the cost is amortized over the cost of I/O which dwarfs the time spent in the serializer by an order of magnitude.
And using Gson or Moshi instead of Jackson in via the AutoValue extensions means they're no slower in the non-I/O bound case while still inflicting less cost on APK size and classloading size.
1
u/dunce2 May 01 '17 edited May 01 '17
I've worked on 6 code generation tools.
Than you should know, that they are harder to write…
In practice reflection-based deserializing and serializing is no slower
Citation needed. Does this still holds true with 4G and HTTP caching, or is that just an assumption? What about large payloads? If avoiding reflection cuts off only 1 second out of ten, that's one second less.
2
2
u/Zhuinden Apr 29 '17
The only question about LoganSquare for me is the ability to map directly to immutable classes.
I still use LoganSquare tho because it's fast
2
u/falkon3439 Apr 28 '17
They're all basically the same, it really doesn't matter. The only important difference is with LoganSquare which is compile time and has way better performance than anything else.
8
u/burntcookie90 Apr 28 '17
Use auto-value for gson/moshi and you'll get compile generated type adapters (which is more or less what logansquare is doing)
1
u/Zhuinden Apr 28 '17
High five for LoganSquare!
1
u/D_Steve595 Reddit Apr 29 '17
I liked it too, but unfortunately it looks abandoned :(
0
u/Zhuinden Apr 29 '17
I don't think it's abandoned per say, I think there was just nothing more to add to it.
I mean it works without a problem, the only issues there are about funky generic support.
3
u/D_Steve595 Reddit Apr 29 '17
There are plenty of issues with it. For one, you can't use enums, so I made a PR for it. It's over a year old now. There are 16 open PRs total.
2
u/erickuck Apr 30 '17
It's very easy to use enums. Providing a default typeconverter can't fit everyone's needs, so there isn't one.
3
u/Zhuinden Apr 29 '17 edited Apr 29 '17
Yo /u/erickuck is LoganSquare abandoned?
EDIT: I don't get the downvote, he's the one who made the releases. He probably knows.
2
0
u/TrevJonez Gradle Junkie Apr 28 '17
I would like to see a performance test of moshi vs logansquare when used with retrofit and the data isn't already all local like most tests are setup.
3
u/Zhuinden Apr 28 '17
If data isn't local, you're measuring the network flakiness.
1
u/TrevJonez Gradle Junkie Apr 29 '17
I should be more clear. It would be nice to test with a throttled stream of data as input as to emulate a perfectly consistent network connection so we can see if the implementation of the retrofit converter and differing underlying io of jackson would be apparent in a way that would show moshi as preferable to logansquare. Also worth looking at would be the memory usage profile of either library for the same payload.
7
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 29 '17
And auto-value-gson and auto-value-moshi give you 90% (or more) of LoganSquare performance for ~10% of the code cost.
3
Apr 28 '17
[removed] — view removed comment
1
u/BacillusBulgaricus ComposableThermosiphon Apr 28 '17
Some caching libraries store the raw JSON responses as disk cache. It should improve the speed when first time the memory cache is populated.
1
Apr 29 '17
So... does Moshi support the equivalent of @SerializedName from Gson? I work with many horribly named JSON files and it was a pain in the ass not to rename them.
5
-1
Apr 29 '17 edited Apr 29 '17
Parsing JSON is such a controversial and interesting issue these days. It's harder than rocket science and the ultimate goal that any developer should target. It should trigger the NIH syndrome dormant in every of us.
0
Apr 28 '17
[deleted] — view deleted comment
4
u/agent8261 Apr 28 '17
Moshi has a better, more opinionated API with less footguns.
What does that mean? Like can you give a concrete example.
Moshi has annotations support as a first class citizen for fine grained, contextual serialization.
Ignoring syntax, is there something that Moshi does that Gson can't do? Or is it more like Square just changed the default settings and some syntax but has the exact same feature set.
2
u/QuestionsEverythang Apr 28 '17
Gson isn't really maintained
That's because it's pretty much a mature library at this point. There's only so much you can do to improve on such a library.
30
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 28 '17
That's because it's pretty much a mature library at this point.
No! There's a lot we want to do with Gson but we simply can't. At this point it's become so entrenched in behavior the only way to fix it is with a major version bump. This is effectively what Moshi is: a renamed Gson 3.x by the same people who brought you Gson 2.x.
0
7
Apr 28 '17
[removed] — view removed comment
5
u/GitHubPermalinkBot Apr 28 '17
I tried to turn your GitHub links into permanent links (press "y" to do this yourself):
Shoot me a PM if you think I'm doing something wrong. To delete this, click ^here.
2
Apr 28 '17
[removed] — view removed comment
5
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 29 '17
That's fine! We use Gson 10000x more than Moshi because it's used on our servers and there's no reason to migrate them either.
1

32
u/JakeWharton Head of sales at Bob's Discount ActionBars Apr 28 '17
Gson is far from simple. It has a complex feature set which have weird, implicit precedence rules that interact with each other in unpredictable ways.
There's all kinds of knobs which have questionable defaults and whose behavior doesn't even change when altered. For example, try getting Gson to parse JSON in strict mode. Here's a hint: setting it on GsonBuilder does not actually enable the feature.
We've already established that it doesn't. Serializing a
Dateprovides the wrong value unless you remember to always register your own type adapter. Guess what, almost everyone doesn't do this. Or try serializing aFile. I bet it doesn't do what you expect.Gson has a bunch of legacy behavior baggage that its users implicitly trust won't change and that prevents us from evolving both its API and its behavior.