extern crate serde_json;
use {
Coordinate,
DataValue,
DataValueType,
Entity,
EntityType,
EntityValue,
LocaleString,
MonoLingualText,
QuantityValue,
Reference,
SearchResults,
SearchResultEntity,
SearchQuery,
SiteLink,
Snak,
SnakType,
Statement,
StatementRank,
TimeValue,
Value,
WikibaseError
};
use std;
pub fn entity_from_json(json: &serde_json::Value)
-> Result<Entity, WikibaseError> {
let id = match &json["id"].as_str() {
&Some(value) => value.to_string(),
&None => return Err(WikibaseError::Serialization("ID missing".to_string()))
};
match &json.get("missing") {
&Some(_) => {
return Ok(
Entity::new(id, vec![], vec![], vec![], vec![], None, true)
)
}
&None => {}
};
let descriptions = locale_strings_from_json(&json, "descriptions")?;
let aliases = locale_string_array_from_json(&json, "aliases")?;
let labels = locale_strings_from_json(&json, "labels")?;
let statements = statements_from_json(&json)?;
let sitelinks = sitelinks_from_json(&json)?;
Ok(Entity::new(
id,
labels,
descriptions,
aliases,
statements,
sitelinks,
false))
}
pub fn search_result_entities_from_json(
json: &serde_json::Value,
query: &SearchQuery
) -> Result<SearchResults, WikibaseError> {
let results_json = match &json["search"].as_array() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("No search results".to_string()))
};
let mut results = vec![];
for result in results_json {
results.push(search_result_entity_from_json(&result, &query)?);
}
Ok(SearchResults::new(results))
}
fn search_result_entity_from_json(
result_json: &serde_json::Value,
query: &SearchQuery
) -> Result<SearchResultEntity, WikibaseError> {
let id = match result_json["id"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Search result ID".to_string()))
};
let label_text = match result_json["label"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Search result label".to_string()))
};
let label = LocaleString::new("en", label_text);
let description = match result_json["description"].as_str() {
Some(value) => Some(LocaleString::new("en", value)),
None => None
};
let aliases = aliases_from_json(result_json, &query)?;
let entity_type = EntityType::new_from_id(id)?;
Ok(SearchResultEntity::new(id, entity_type, label, description, aliases))
}
fn aliases_from_json(
json_value: &serde_json::Value,
query: &SearchQuery
) -> Result<Vec<LocaleString>, WikibaseError> {
let aliases_array = match json_value.get("aliases") {
Some(value) => {
match value.as_array() {
Some(value_array) => value_array,
None => return Err(WikibaseError::Serialization("Aliases array".to_string()))
}
},
None => return Ok(vec![])
};
let mut aliases = vec![];
for alias in aliases_array.iter() {
match alias.as_str() {
Some(value) => aliases.push(
LocaleString::new(query.search_lang(), &value)),
None => return Err(WikibaseError::Serialization("Aliases string".to_string()))
};
}
Ok(aliases)
}
pub fn float_from_json(value: &serde_json::Map<std::string::String,
serde_json::Value>, key: &str) -> Option<f64> {
let single_value = match value.get(key) {
Some(value) => value,
None => return None
};
let value_string = match single_value.as_str() {
Some(value) => value,
None => return None,
};
match value_string.parse() {
Ok(value) => Some(value),
Err(_) => None
}
}
pub fn statement_from_json(json_claim: &serde_json::Value)
-> Result<Statement, WikibaseError> {
let claim_object = match &json_claim.as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Statement".to_string()))
};
let claim_type = match claim_object["type"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Statement type error".to_string()))
};
let rank_string = match claim_object["rank"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Statement rank error".to_string()))
};
let rank = match rank_string {
"deprecated" => StatementRank::Deprecated,
"normal" => StatementRank::Normal,
"preferred" => StatementRank::Preferred,
_ => return Err(WikibaseError::Serialization("Statement rank error".to_string()))
};
let main_snak = match &claim_object["mainsnak"].as_object() {
&Some(snak_json) => {
snak_from_json(snak_json)?
}
&None => return Err(WikibaseError::Serialization("Main snak".to_string()))
};
let qualifiers = match &claim_object.get("qualifiers") {
&Some(qualifiers) => snaks_object_from_json(&qualifiers)?,
&None => vec![]
};
let references = match &claim_object.get("references") {
&Some(references_array_json) => reference_array_from_json(&references_array_json)?,
&None => vec![]
};
Ok(Statement::new(claim_type, rank, main_snak, qualifiers, references))
}
fn locale_string_from_json(string_object: &serde_json::Value)
-> Result<LocaleString, WikibaseError> {
let language = match string_object["language"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Can't deserialize language in locale string".to_string()))
};
match string_object["value"].as_str() {
Some(value) => Ok(LocaleString::new(language, value)),
None => Err(WikibaseError::Serialization("Can't deserialize value in locale string".to_string()))
}
}
fn locale_string_array_from_json(item: &serde_json::Value, key: &str)
-> Result<Vec<LocaleString>, WikibaseError> {
let mut aliases = vec![];
let lang_object = match &item[key].as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Locale object".to_string()))
};
for (language, string_array_json) in lang_object.iter() {
let string_array = match string_array_json.as_array() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Locale array".to_string()))
};
for item_json in string_array.iter() {
match item_json["value"].as_str() {
Some(value) => aliases.push(LocaleString::new(language.to_string(), value.to_string())),
None => return Err(WikibaseError::Serialization("Locale value".to_string()))
}
}
}
Ok(aliases)
}
fn locale_strings_from_json(item: &serde_json::Value, key: &str)
-> Result<Vec<LocaleString>, WikibaseError> {
let mut labels = vec![];
let label_object = match &item.get(key) {
&Some(value) => {
match value.as_object() {
Some(object) => object,
None => return Err(WikibaseError::Serialization("Locale string object not valid".to_string()))
}
}
&None => return Err(WikibaseError::Serialization(format!("Key \"{}\" not found in object", key)))
};
for (_, string_object) in label_object.iter() {
labels.push(locale_string_from_json(string_object)?);
}
Ok(labels)
}
fn statements_from_json(item: &serde_json::Value)
-> Result<Vec<Statement>, WikibaseError> {
let statements_array = match &item["claims"].as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Key \"claims\" missing in json object".to_string()))
};
let mut statements = vec![];
for (_, property_statements) in statements_array.iter() {
let property_statements_array = match &property_statements.as_array() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Statement array".to_string()))
};
for property_statement in property_statements_array.iter() {
statements.push(statement_from_json(&property_statement)?);
}
}
Ok(statements)
}
fn snak_from_json(snak_json: &serde_json::Map<std::string::String,
serde_json::Value>) -> Result<Snak, WikibaseError> {
let datatype = match snak_json["datatype"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Datatype".to_string()))
};
let property = snak_json["property"].as_str().unwrap_or_else(|| {""});
let snak_type = snak_json["snaktype"].as_str().unwrap_or_else(|| {""});
if snak_type == "somevalue" {
let snak = Snak::new(datatype, property, SnakType::UnknownValue, None);
return Ok(snak)
}
if snak_type == "novalue" {
let snak = Snak::new(datatype, property, SnakType::NoValue, None);
return Ok(snak)
}
let data_value = match snak_json["datavalue"].as_object() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Data value not found".to_string()))
};
let data_value_type = match data_value["type"].as_str() {
Some(value) => {
DataValueType::new_from_str(value)?
}
None => return Err(WikibaseError::Serialization("Not type in data value".to_string()))
};
match data_value_type {
DataValueType::EntityId => {
let value_object = match data_value["value"].as_object() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Error serializing value object".to_string()))
};
let entity_value = EntityValue::new_from_object(value_object)?;
let statement_value = Value::Entity(entity_value);
let data_value = DataValue::new(data_value_type, statement_value);
Ok(Snak::new(datatype, property, SnakType::Value, Some(data_value)))
}
DataValueType::Quantity => {
let value_object = match data_value["value"].as_object() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Error serializing value object".to_string()))
};
let quantity_value = QuantityValue::new_from_object(value_object)?;
let statement_value = Value::Quantity(quantity_value);
let data_value = DataValue::new(data_value_type, statement_value);
Ok(Snak::new(datatype, property, SnakType::Value, Some(data_value)))
}
DataValueType::GlobeCoordinate => {
let value_object = match data_value["value"].as_object() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Error serializing value object".to_string()))
};
let coordinate = Coordinate::new_from_json(value_object)?;
let coordinate_statement = Value::Coordinate(coordinate);
let data_value = DataValue::new(data_value_type, coordinate_statement);
Ok(Snak::new(datatype, property, SnakType::Value, Some(data_value)))
}
DataValueType::Time => {
let value_object = match data_value["value"].as_object() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Error serializing value object".to_string()))
};
let time_value_struct = TimeValue::new_from_object(value_object);
let time_value = Value::Time(time_value_struct);
let data_value = DataValue::new(data_value_type, time_value);
Ok(Snak::new(datatype, property, SnakType::Value, Some(data_value)))
}
DataValueType::MonoLingualText => {
let value_object = match data_value["value"].as_object() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Error serializing value object".to_string()))
};
let mono_lingual_text = MonoLingualText::new_from_json(value_object)?;
let mono_lingual_text_value = Value::MonoLingual(mono_lingual_text);
let data_value = DataValue::new(data_value_type, mono_lingual_text_value);
Ok(Snak::new(datatype, property, SnakType::Value, Some(data_value)))
}
DataValueType::StringType => {
let value_string = match data_value["value"].as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Error serializing value string".to_string()))
};
let statement_value = Value::StringValue(value_string.to_string());
let data_value = DataValue::new(data_value_type, statement_value);
Ok(Snak::new(datatype, property, SnakType::Value, Some(data_value)))
}
}
}
fn snaks_object_from_json(snaks_object_json: &serde_json::Value)
-> Result<Vec<Snak>, WikibaseError> {
let mut snaks = vec![];
let snaks_object = match &snaks_object_json.as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Can't deserialize snaks object".to_string()))
};
for (_, property_snaks) in snaks_object.iter() {
let snak_array = match &property_snaks.as_array() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Can't deserialize snak array".to_string()))
};
for snak_json in snak_array.iter() {
let snak_object = match &snak_json.as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Can't deserialize snak object".to_string()))
};
snaks.push(snak_from_json(snak_object)?);
}
}
Ok(snaks)
}
fn reference_array_from_json(references_array_json: &serde_json::Value)
-> Result<Vec<Reference>, WikibaseError> {
let mut references = vec![];
let reference_array = match &references_array_json.as_array() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Reference array".to_string()))
};
for references_object_json in reference_array.iter() {
let reference_object = match &references_object_json.as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Reference object".to_string()))
};
let snaks_array = match &reference_object.get("snaks") {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Reference snak object".to_string()))
};
references.push(Reference::new(snaks_object_from_json(snaks_array)?));
}
Ok(references)
}
fn string_vector_from_json(json_values: &Vec<serde_json::Value>)
-> Result<Vec<String>, WikibaseError> {
let mut values = vec![];
for json_value in json_values {
let value = match json_value.as_str() {
Some(value) => value,
None => return Err(WikibaseError::Serialization("Error serializing string vector".to_string()))
};
values.push(value.to_string());
}
Ok(values)
}
fn sitelinks_from_json(item: &serde_json::Value)
-> Result<Option<Vec<SiteLink>>, WikibaseError> {
let sitelinks_array = match &item.get("sitelinks") {
&Some(value) => {
match value.as_object() {
Some(value_object) => value_object,
None => return Err(WikibaseError::Serialization("Key \"sitelinks\" missing in json object".to_string()))
}
}
&None => return Ok(None)
};
let mut sitelinks = vec![];
for (site_id, sitelink_object_json) in sitelinks_array.iter() {
let sitelink_object = match &sitelink_object_json.as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Error serializing sitelink object".to_string()))
};
let title = match &sitelink_object["title"].as_str() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Error serializing sitelink title".to_string()))
};
let badges = match &sitelink_object["badges"].as_array() {
&Some(value) => {
string_vector_from_json(value)?
}
&None => return Err(WikibaseError::Serialization("Error serializing badges array".to_string()))
};
let sitelink = SiteLink::new(site_id.to_string(), title.to_string(), badges);
sitelinks.push(sitelink);
}
Ok(Some(sitelinks))
}