Изменение коэффициента на числовое из данных Messy [дубликат]

Ваш JSON содержит литеральную строку для объектов "body", которые фактически встроены, с двойным сериализованным JSON. Чтобы десериализовать это в иерархию POCO без необходимости вводить промежуточное свойство суррогата string Json внутри любого из ваших типов, у вас есть несколько вариантов:

  1. Вы можете предварительно обработать ваш JSON, используя LINQ к 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();
    
  2. Вы можете ввести общий 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; }
}

3
задан Bryan P 3 January 2014 в 00:13
поделиться

4 ответа

В 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
8
ответ дан Roland 25 August 2018 в 21:24
поделиться

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 
0
ответ дан Madhulika Chaudhry 25 August 2018 в 21:24
поделиться

Это то же самое, что и решение Роланда, за исключением использования пакета stringr. При работе со строками я рекомендую его, хотя интерфейс более интуитивно понятен.

library(stringr)
d <- str_replace(junk$percent.error, pattern="%", "")
junk$percent.error <- as.numeric(d)/100
2
ответ дан Mark Heckmann 25 August 2018 в 21:24
поделиться

С помощью data.table вы можете достичь этого как

a <- fread("file.csv")[,`percent error` := as.numeric(sub('%', '', `percent error`))/100]
1
ответ дан Ott Toomet 25 August 2018 в 21:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: