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
use crate::config::{Config, SerializeMode};
use crate::error::StamError;
use crate::file::*;
use crate::types::*;

pub trait ToJson
where
    Self: TypeInfo + serde::Serialize,
{
    /// Writes a serialisation (choose a dataformat) to any writer
    /// Lower-level function
    fn to_json_writer<W>(&self, writer: W, compact: bool) -> Result<(), StamError>
    where
        W: std::io::Write,
    {
        match compact {
            false => serde_json::to_writer_pretty(writer, &self).map_err(|e| {
                StamError::SerializationError(format!(
                    "Writing {} to file: {}",
                    Self::typeinfo(),
                    e
                ))
            }),
            true => serde_json::to_writer(writer, &self).map_err(|e| {
                StamError::SerializationError(format!(
                    "Writing {} to file: {}",
                    Self::typeinfo(),
                    e
                ))
            }),
        }
    }

    /// Writes this structure to a file
    /// The actual dataformat can be set via `config`, the default is STAM JSON.
    fn to_json_file(&self, filename: &str, config: &Config) -> Result<(), StamError> {
        debug(config, || {
            format!("{}.to_file: filename={:?}", Self::typeinfo(), filename)
        });
        if let Type::TextResource | Type::AnnotationDataSet = Self::typeinfo() {
            //introspection to detect whether type can do @include
            config.set_serialize_mode(SerializeMode::NoInclude); //set standoff mode, what we're about the write is the standoff file
        }
        let compact = match config.dataformat {
            DataFormat::Json { compact } => compact,
            _ => {
                if let Type::AnnotationStore = Self::typeinfo() {
                    return Err(StamError::SerializationError(format!(
                        "Unable to serialize to JSON for {} (filename {}) when config dataformat is set to {}",
                        Self::typeinfo(),
                        filename,
                        config.dataformat
                    )));
                } else {
                    false
                }
            }
        };
        let writer = open_file_writer(filename, &config)?;
        let result = self.to_json_writer(writer, compact);
        if let Type::TextResource | Type::AnnotationDataSet = Self::typeinfo() {
            //introspection to detect whether type can do @include
            config.set_serialize_mode(SerializeMode::AllowInclude); //set standoff mode, what we're about the write is the standoff file
        }
        result
    }

    /// Serializes this structure to one string.
    /// The actual dataformat can be set via `config`, the default is STAM JSON.
    /// If `config` not not specified, an attempt to fetch the AnnotationStore's initial config is made
    fn to_json_string(&self, config: &Config) -> Result<String, StamError> {
        if let Type::TextResource | Type::AnnotationDataSet = Self::typeinfo() {
            //introspection to detect whether type can do @include
            config.set_serialize_mode(SerializeMode::NoInclude); //set standoff mode, what we're about the write is the standoff file
        }
        let result = match config.dataformat {
            DataFormat::Json { compact: false } => {
                serde_json::to_string_pretty(&self).map_err(|e| {
                    StamError::SerializationError(format!(
                        "Writing {} to string: {}",
                        Self::typeinfo(),
                        e
                    ))
                })
            }
            DataFormat::Json { compact: true } => serde_json::to_string(&self).map_err(|e| {
                StamError::SerializationError(format!(
                    "Writing {} to string: {}",
                    Self::typeinfo(),
                    e
                ))
            }),
            _ => Err(StamError::SerializationError(format!(
                "Unable to serialize to JSON for {} when config dataformat is set to {}",
                Self::typeinfo(),
                config.dataformat
            ))),
        };
        if let Type::TextResource | Type::AnnotationDataSet = Self::typeinfo() {
            //introspection to detect whether type can do @include
            config.set_serialize_mode(SerializeMode::AllowInclude); //set standoff mode, what we're about the write is the standoff file
        }
        result
    }
}

pub trait FromJson<'a>
where
    Self: TypeInfo + serde::Deserialize<'a>,
{
    fn from_json_file(filename: &str, config: Config) -> Result<Self, StamError>;

    fn from_json_str(string: &str, config: Config) -> Result<Self, StamError>;
}