Ваш JSON содержит литеральную строку для объектов "body"
, которые фактически встроены, с двойным сериализованным JSON. Чтобы десериализовать это в иерархию POCO без необходимости вводить промежуточное свойство суррогата string Json
внутри любого из ваших типов, у вас есть несколько вариантов:
"body"
на их проанализированные эквиваленты: var rootToken = JToken.Parse(json);
foreach (var token in rootToken.SelectTokens("responses[*].body").ToList().Where(t => t.Type == JTokenType.String))
{
token.Replace(JToken.Parse((string)token));
}
var root = rootToken.ToObject();
JsonConverter
для POCO, соответствующий каждому объекту Body
, который анализирует входящий встроенный строковый литерал JSON в иерархию LINQ to JSON
, затем десериализует следующее: public class EmbeddedLiteralConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var contract = serializer.ContractResolver.ResolveContract(objectType);
if (contract is JsonPrimitiveContract)
throw new JsonSerializationException("Invalid type: " + objectType);
if (existingValue == null)
existingValue = contract.DefaultCreator();
if (reader.TokenType == JsonToken.String)
{
var json = (string)JToken.Load(reader);
using (var subReader = new JsonTextReader(new StringReader(json)))
{
// By populating a pre-allocated instance we avoid an infinite recursion in EmbeddedLiteralConverter.ReadJson()
// Re-use the existing serializer to preserve settings.
serializer.Populate(subReader, existingValue);
}
}
else
{
serializer.Populate(reader, existingValue);
}
return existingValue;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Затем используйте его как: var root = JsonConvert.DeserializeObject(json, new EmbeddedLiteralConverter());
Обратите внимание, что конвертер проверяет, является ли входящий токен JSON строкой, а если нет, десериализуется напрямую. Таким образом, преобразователь должен использоваться, когда "body"
JSON является и не имеет двойного сериализации. В целях тестирования я создал следующие целевые классы, используя http: // json2csharp. com / :
public class Error
{
public string message { get; set; }
public string type { get; set; }
public int code { get; set; }
}
public class Body
{
public Error error { get; set; }
}
public class Respons
{
public string info { get; set; }
public Body body { get; set; }
}
public class RootObject
{
public List responses { get; set; }
}
В R. Нет никакого «процентного» типа. Поэтому вам нужно выполнить некоторую пост-обработку:
DF <- read.table(text="actual,simulated,percent error
2.1496,8.6066,-300%
0.9170,8.0266,-775%
7.9406,0.2152,97%
4.9637,3.5237,29%", sep=",", header=TRUE)
DF[,3] <- as.numeric(gsub("%", "",DF[,3]))/100
# actual simulated percent.error
#1 2.1496 8.6066 -3.00
#2 0.9170 8.0266 -7.75
#3 7.9406 0.2152 0.97
#4 4.9637 3.5237 0.29
Tidyverse имеет несколько способов решения таких проблем. Вы можете использовать спецификацию parse_number (), которая будет лишать номер с любыми символами, текстом и т. Д .:
sample_data = "actual,simulated,percent error\n 2.1496,8.6066,-300%\n 0.9170,8.0266,-775%\n7.9406,0.2152,97%\n4.9637,3.5237,29%"
DF <- read_csv(sample_data,col_types = cols(`percent error`= col_number()))
# A tibble: 4 x 3
# actual simulated `percent error`
# <chr> <dbl> <dbl>
# 1 2.1496 8.61 -300
# 2 + 0.9170 8.03 -775
# 3 + 7.9406 0.215 97.0
# 4 + 4.9637 3.52 29.0
Это то же самое, что и решение Роланда, за исключением использования пакета stringr
. При работе со строками я рекомендую его, хотя интерфейс более интуитивно понятен.
library(stringr)
d <- str_replace(junk$percent.error, pattern="%", "")
junk$percent.error <- as.numeric(d)/100
С помощью data.table
вы можете достичь этого как
a <- fread("file.csv")[,`percent error` := as.numeric(sub('%', '', `percent error`))/100]