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
// Copyright (c) 2018 The openrtb-rust authors
//
// 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.

use super::seat_bid::SeatBid;
use serde_utils;

// 4.2.1 Object: BidResponse
//
// This object is the top-level bid response object (i.e., the unnamed outer
// JSON object). The id attribute is a reflection of the bid request ID for
// logging purposes. Similarly, bidid is an optional response tracking ID for
// bidders. If specified, it can be included in the subsequent win notice call
// if the bidder wins. At least one seatbid object is required, which contains
// at least one bid for an impression. Other attributes are optional.
// To express a “no-bid”, the options are to return an empty response with
// HTTP 204. Alternately if the bidder wishes to convey to the exchange a
// reason for not bidding, just a BidResponse object is returned with a reason
// code in the nbr attribute.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct BidResponse {
    // Required. ID of the bid request to which this is a response.
    pub id: String,

    #[serde(rename = "seatbid", default, skip_serializing_if = "Vec::is_empty")]
    pub seat_bid: Vec<SeatBid>,

    #[serde(rename = "bidid", skip_serializing_if = "Option::is_none")]
    pub bid_id: Option<String>,

    #[serde(rename = "cur", skip_serializing_if = "Option::is_none")]
    pub currency: Option<String>,

    #[serde(rename = "customdata", skip_serializing_if = "Option::is_none")]
    pub custom_data: Option<String>,

    #[serde(rename = "nbr", skip_serializing_if = "Option::is_none")]
    pub no_bidding_reason: Option<u32>,

    // Placeholder for exchange-specific extensions to OpenRTB.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub ext: Option<serde_utils::Ext>,
}

impl BidResponse {
    pub fn new(id: String) -> BidResponse {
        BidResponse {
            id: id,
            seat_bid: vec![],
            bid_id: None,
            currency: None,
            custom_data: None,
            no_bidding_reason: None,
            ext: None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json;

    #[test]
    fn serialization_skip_fields() {
        let b = BidResponse {
            id: "1234".to_string(),
            seat_bid: vec![],
            bid_id: None,
            currency: None,
            custom_data: None,
            no_bidding_reason: None,
            ext: None,
        };

        let expected = r#"{"id":"1234"}"#;
        let serialized = serde_json::to_string(&b).unwrap();

        assert_eq!(expected, serialized)
    }

    #[test]
    fn deserialize_defaults() {
        let serialized = r#"{
            "id": "1234"
        }"#;

        let res = serde_json::from_str(serialized);

        let b: BidResponse = match res {
            Ok(x) => x,
            Err(e) => panic!("{:?}", e),
        };

        let expected = BidResponse {
            id: "1234".to_string(),
            seat_bid: vec![],
            bid_id: None,
            currency: None,
            custom_data: None,
            no_bidding_reason: None,
            ext: None,
        };

        assert_eq!(expected.id, b.id);
    }
}