From bb809992ad543ea4c0c31897fbf2d130394dd80e Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Sat, 5 Sep 2020 13:18:50 +0200 Subject: Add json output format This patch adds a new output format, JSON. It uses serde to serialize the output types. todo: man page, changelog --- src/output.rs | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'src/output.rs') diff --git a/src/output.rs b/src/output.rs index 7c85a82..37daf92 100644 --- a/src/output.rs +++ b/src/output.rs @@ -5,8 +5,11 @@ //! Defines data types that can be formatted in different output formats. +use std::collections; use std::fmt; +use anyhow::Context as _; + use crate::args; use crate::Context; @@ -33,17 +36,21 @@ pub trait Output { } /// A single object. -pub struct Value(T); +pub struct Value { + key: String, + value: T, +} /// A list of objects of the same type that is displayed as a table with a fallback message for an /// empty list. pub struct Table { + key: String, items: Vec, empty_message: String, } /// A trait for objects that can be displayed in a table. -pub trait TableItem { +pub trait TableItem: serde::Serialize { /// Returns the column headers for this type of table items. fn headers() -> Vec<&'static str>; /// Returns the values of the column for this table item. @@ -56,23 +63,28 @@ pub struct TextObject { items: Vec<(usize, String, String)>, } -impl Value { - pub fn new(value: T) -> Value { - Value(value) +impl Value { + pub fn new(key: impl Into, value: T) -> Value { + Value { + key: key.into(), + value, + } } } -impl Output for Value { +impl Output for Value { fn format(&self, format: args::OutputFormat) -> anyhow::Result { match format { - args::OutputFormat::Text => Ok(self.0.to_string()), + args::OutputFormat::Json => get_json(&self.key, &self.value), + args::OutputFormat::Text => Ok(self.value.to_string()), } } } impl Table { - pub fn new(empty_message: impl Into) -> Table { + pub fn new(key: impl Into, empty_message: impl Into) -> Table { Table { + key: key.into(), items: Vec::new(), empty_message: empty_message.into(), } @@ -90,6 +102,7 @@ impl Table { impl Output for Table { fn format(&self, format: args::OutputFormat) -> anyhow::Result { match format { + args::OutputFormat::Json => get_json(&self.key, &self.items), args::OutputFormat::Text => { if self.items.is_empty() { Ok(self.empty_message.clone()) @@ -173,3 +186,9 @@ impl fmt::Display for TextObject { Ok(()) } } + +fn get_json(key: &str, value: &T) -> anyhow::Result { + let mut map = collections::HashMap::new(); + let _ = map.insert(key, value); + serde_json::to_string_pretty(&map).context("Could not serialize output to JSON") +} -- cgit v1.2.1