1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! JSON Builders
//!
//! This module provides Builders that simplify constructing complex `Value`s. This can be useful
//! when dynamically constructing a `Value`, or when it is inconvenient to write a custom
//! `Serialize` implementation or to use `#[derive(Serialize)]`.
//!
//! # Example
//!
//! ```rust
//! use serde_json::builder::ObjectBuilder;
//!
//! let value = ObjectBuilder::new()
//!     .insert("name", "point")
//!     .insert_array("points", |builder| {
//!         builder
//!             .push_object(|builder| {
//!                 builder.insert("x", 1).insert("y", 2)
//!             })
//!             .push_object(|builder| {
//!                 builder.insert("x", 3).insert("y", 4)
//!             })
//!     })
//!     .unwrap();
//! ```

use std::collections::BTreeMap;

use serde::ser;

use value::{self, Value};

/// This structure provides a simple interface for constructing a JSON array.
pub struct ArrayBuilder {
    array: Vec<Value>,
}

impl ArrayBuilder {
    /// Construct an `ObjectBuilder`.
    pub fn new() -> ArrayBuilder {
        ArrayBuilder { array: Vec::new() }
    }

    /// Return the constructed `Value`.
    pub fn unwrap(self) -> Value {
        Value::Array(self.array)
    }

    /// Insert a value into the array.
    pub fn push<T: ser::Serialize>(mut self, v: T) -> ArrayBuilder {
        self.array.push(value::to_value(&v));
        self
    }

    /// Creates and passes an `ArrayBuilder` into a closure, then inserts the resulting array into
    /// this array.
    pub fn push_array<F>(mut self, f: F) -> ArrayBuilder where
        F: FnOnce(ArrayBuilder) -> ArrayBuilder
    {
        let builder = ArrayBuilder::new();
        self.array.push(f(builder).unwrap());
        self
    }

    /// Creates and passes an `ArrayBuilder` into a closure, then inserts the resulting object into
    /// this array.
    pub fn push_object<F>(mut self, f: F) -> ArrayBuilder where
        F: FnOnce(ObjectBuilder) -> ObjectBuilder
    {
        let builder = ObjectBuilder::new();
        self.array.push(f(builder).unwrap());
        self
    }
}

/// This structure provides a simple interface for constructing a JSON object.
pub struct ObjectBuilder {
    object: BTreeMap<String, Value>,
}

impl ObjectBuilder {
    /// Construct an `ObjectBuilder`.
    pub fn new() -> ObjectBuilder {
        ObjectBuilder { object: BTreeMap::new() }
    }

    /// Return the constructed `Value`.
    pub fn unwrap(self) -> Value {
        Value::Object(self.object)
    }

    /// Insert a key-value pair into the object.
    pub fn insert<S, V>(mut self, key: S, value: V) -> ObjectBuilder
        where S: Into<String>,
              V: ser::Serialize,
    {
        self.object.insert(key.into(), value::to_value(&value));
        self
    }

    /// Creates and passes an `ObjectBuilder` into a closure, then inserts the resulting array into
    /// this object.
    pub fn insert_array<S, F>(mut self, key: S, f: F) -> ObjectBuilder
        where S: Into<String>,
              F: FnOnce(ArrayBuilder) -> ArrayBuilder
    {
        let builder = ArrayBuilder::new();
        self.object.insert(key.into(), f(builder).unwrap());
        self
    }

    /// Creates and passes an `ObjectBuilder` into a closure, then inserts the resulting object into
    /// this object.
    pub fn insert_object<S, F>(mut self, key: S, f: F) -> ObjectBuilder
        where S: Into<String>,
              F: FnOnce(ObjectBuilder) -> ObjectBuilder
    {
        let builder = ObjectBuilder::new();
        self.object.insert(key.into(), f(builder).unwrap());
        self
    }
}