Skip to content

0.9.0

Compare
Choose a tag to compare
@maciejhirsz maciejhirsz released this 16 Jul 11:41
· 122 commits to master since this release

Breaking changes

  • JsonValue got a lot of work put into it:
    • The Object variant has changed from storing BTreeMap<String, JsonValue> to storing a new json::object::Object type.
    • A new Short variant has been added, storing the new json::short::Short type. Those are short (up to 30 bytes) strings that can be allocated on the stack at no additional cost to memory on 64bit architecture.
  • JsonResult and JsonError have been renamed to just Result and Error respectively (see issue #38). Aliases have been provided to keep things backwards compatible, but the old names are considered deprecated and you are advised to migrate to the new ones.
  • On top of the name change, the Error enum no longer has the ArrayIndexOutOfBounds variant. It hasn't been used for a while.
  • Members, MembersMut, Entries and EntriesMut are no longer enums and cannot be pattern-matched (read below about iterator improvements).
  • The Entries and EntriesMut iterators now yield &str instead of &String as the first member of the entry tuple. Depending on your implementation this might or might not be a breaking change (as &String would automatically deref to &str anyway).

Shorts

The new Short variant should be completely transparent to you, and shouldn't in any way affect how you use the library. They are both considered strings as far as all methods are concerned. When creating new values, the right type is chosen for you:

// create a JsonValue::Short
data["foo"] = "bar".into(); 

// create a JsonValue::String (from Neal Stephenson's "Anathem")
data["quote"] = "And it happened all the time that the compromise \
                 between two perfectly rational alternatives was something \
                 that made no sense at all.".into();

// Both are considered strings, and all string methods work on both
assert!(data["foo"].is_string());
assert!(data["quote"].is_string());

Object keys are now stored in insertion order

The new implementation of the Object type acts as a Binary Search Tree, with the deviation from a standard implementation of BST in that the nodes aren't separately allocated on the heap, but rather are collectively allocated on an internal vector, reducing allocations and preserving insertion order. This means that all objects are now stringified in the same order they were parsed or instantiated (see issue #68).

Performance improvements

  • The new Short type, as well as the new Object type, both exploit the fact that short strings don't have to be separately allocated on the heap. JSON is, after all, an Object Notation where all keys and plenty of data are nothing but strings. Avoiding the unnecessary heap allocations has, in some cases, cut parsing times by half compared to the previous release!
  • Iterators are now much faster too. Previously calling .members() or .entries() would return an enum, which would in turn use pattern matching on each iteration. We are much smarter now. Trying to get an iterator from a wrong type will yield a true empty iterator - those are very cheap to create as they require no heap allocation. In fact, the Members and MembersMut iterators are now just type aliases for std::slice::Iter<'a, JsonValue> and std::slice::IterMut<'a, JsonValue>. Thanks to @zummenix for the work done on this (see issue #67).
  • A very minor thing, but moving away from BTreeMap for object storage, means the JsonValue enum on 64bit architecture now dropped from being 40 bytes to 32 bytes long.

Apache 2.0 License

In good Rust fashion, Apache 2.0 license has been added as an option.