Code Quality Rank: L5
Programming language: Swift
License: MIT License
Tags: Data Management     JSON    
Latest version: v0.2.2

Pistachio alternatives and similar libraries

Based on the "JSON" category.
Alternatively, view Pistachio alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of Pistachio or a related project?

Add another 'JSON' Library



Pistachio is a generic model framework. By leveraging lenses and value transformers, it allows you to create type safe adapters for any recursive data structure, be it JSON, YAML or XML.

If you are already familiar with Argo, take a look at Pistachiargo.



Carthage is a simple, decentralized dependency manager for Cocoa.

  1. Add Pistachio to your Cartfile:
  github "felixjendrusch/Pistachio" ~> 0.2
  1. Run carthage update to fetch and build Pistachio and its dependencies.

  2. Make sure your application's target links against Pistachio.framework and copies all relevant frameworks into its application bundle (iOS); or embeds the binaries of all relevant frameworks (Mac).


Let's start by defining a very simple model:

struct Origin {
  var city: String

  init(city: String = "") {
    self.city = city
struct Person {
  var name: String
  var origin: Origin

  init(name: String = "", origin: Origin = Origin()) {
    self.name = name
    self.origin = origin

A lens is basically just a combination of a getter and a setter, providing a view on your model:

struct OriginLenses {
  static let city = Lens(get: { $0.city }, set: { (inout origin: Origin, city) in
    origin.city = city
struct PersonLenses {
  static let name = Lens(get: { $0.name }, set: { (inout person: Person, name) in
    person.name = name

  static let origin = Lens(get: { $0.origin }, set: { (inout person: Person, origin) in
    person.origin = origin

It can be used to access and modify your model:

var person = Person(name: "Felix", origin: Origin(city: "Berlin"))
person = set(PersonLenses.name, person, "Robb")
get(PersonLenses.name, person) // == "Robb"

And you can compose, lift, etc. them:

let composed = PersonLenses.origin >>> OriginLenses.city
person = set(composed, person, "New York")
get(composed, person) // == "New York"

With lenses and value transformers, you can create adapters for your models:

struct Adapters {
  static let origin = DictionaryAdapter(specification: [
    "city_name": map(OriginLenses.city, StringToAnyObjectValueTransformers)
  ], dictionaryTansformer: DictionaryToAnyObjectValueTransformers, value: Origin())

  static let person = DictionaryAdapter(specification: [
    "name": map(PersonLenses.name, StringToAnyObjectValueTransformers),
    "origin": map(PersonLenses.origin, origin)
  ], dictionaryTansformer: DictionaryToAnyObjectValueTransformers, value: Person())

Use fix to create adapters for recursive models:

let adapter: DictionaryAdapter<Key, Value, TransformedValue, Error> = fix { adapter in
  // use `adapter` to reference the currently created adapter

Adapters handle transforming and reverse transforming your models:

let adapter = Adapters.person

var person = Person(name: "Seb", origin: Origin(city: "Berlin"))
var data = adapter.transform(person)
// == .Success(Box([ "name": "Seb", "origin": [ "city_name": "Berlin" ] ]))

// == .Success(Box(person))

Both transform and reverseTransform return a Result, which either holds the (reverse) transformed value or an error. This enables you to gracefully handle transformation errors.