convert only.Expand description
Carrying objects between OCPI versions, with an explicit account of what was lost.
A hub that connects a 2.2.1 CPO to a 2.3.0 eMSP has to translate every object that crosses it.
The translations are not symmetric: going forward is almost always total, going back means
deciding what to do with the fields the older version does not have. Silently dropping them —
which is what a hand-written From impl does — turns a hub into a data shredder that nobody
notices until an invoice is wrong.
So both directions return a Converted<T>: the object, plus a Lossy report naming every
field that could not be carried, by JSON Pointer, with the reason.
use ocpi_kit::convert::{Downgrade, Upgrade};
use ocpi_kit::{v2_2_1, v2_3_0};
// 2.2.1 → 2.3.0: `incl_vat` becomes a VAT tax line.
let old = v2_2_1::Price::with_vat("5.00".parse().unwrap(), "5.50".parse().unwrap());
let new: v2_3_0::Price = old.upgrade().expect_lossless();
assert_eq!(new.taxes.len(), 1);
assert_eq!(new.after_taxes().to_string(), "5.50");
// 2.3.0 → 2.2.1: several named taxes collapse into one `incl_vat`, and that is reported.
let mut multi = v2_3_0::Price::new("5.00".parse().unwrap());
multi.taxes.push(v2_3_0::TaxAmount::new("GST", None, "0.25".parse().unwrap()).unwrap());
multi.taxes.push(v2_3_0::TaxAmount::new("QST", None, "0.50".parse().unwrap()).unwrap());
let back = multi.downgrade();
let old: v2_2_1::Price = back.value;
assert_eq!(old.incl_vat.unwrap().to_string(), "5.75");
assert!(!back.lossy.is_empty(), "the tax names did not survive");§What the direction of a conversion means
Upgradegoes to a newer version. Where the newer version added a required field, the default is chosen from the older version’s semantics and documented on the impl — for example a 2.2.1Tariffbecomes a 2.3.0 one withtax_included: NO, because a 2.2.1PriceComponent.priceis “Price per unit (excl. VAT)” by definition.Downgradegoes to an older version, and is where losses accumulate.
§Enum values survive both directions
Because the enums OCPI 2.3.0 opened are decoded leniently in 2.2.1 too
(ocpi_lenient_enum!), a 2.3.0 ConnectorType::Mcs downgrades to
a 2.2.1 ConnectorType::Custom("MCS") — same string on the wire, no data lost — and upgrades
straight back. Only fields that do not exist in the older version are ever dropped.
Modules§
- v2_
2_ 1_ v2_ 3_ 0 - Conversions between OCPI 2.2.1 and OCPI 2.3.0.
- wire
- Translating a JSON document from one OCPI version to another.
Structs§
- Converted
- The result of a version conversion: the object, and what it cost.
- Loss
- One piece of information that a conversion could not carry.
- Lossy
- Everything a conversion could not carry, in document order.