Member 12885549 Ответов: 2

Синтаксический анализ строки в словаре C#


У меня есть метод, в котором я вызываю другой API. От
var activeCustomers = await response.Content.ReadAsStringAsync();
Я получаю строку, которая содержит объекты [timestamp, value] :

{"values":[[1298937600000,1],[1459468800000,16],[1462060800000,527],[1464739200000,173],[1467331200000,132],[1470009600000,166],[1472688000000,151],[1475280000000,172],[1477958400000,139],[1480550400000,129],[1483228800000,116],[1485907200000,133],[1488326400000,180],[1491004800000,227],[1493596800000,281],[1496275200000,263],[1498867200000,230],[1501545600000,326],[1504224000000,403],[1506816000000,442],[1509494400000,1019],[1512086400000,650],[1514764800000,708],[1564617600000,2614],[1567296000000,2527],[1569888000000,3144],[1572566400000,3075],[1575158400000,2541],[1577836800000,2246],[1580515200000,2456],[1583020800000,885]]}


Я хочу разобрать эти значения в словаре, но я не уверен, что это самый оптимальный способ для этого.

Что я уже пробовал:

I tried <pre>var results = ((IEnumerable) propertyValue).Cast<object>()
но ienumerable был одной большой строкой. Может быть, для этого есть какое-то регулярное выражение?

Maciej Los

Это похоже на данные json. Читайте о сериализации json.

Luc Pattyn

Может быть, не все можно или нужно решить в одной строке кода.

Эта статья покажет вам возможный путь: API JSON.

:)

2 Ответов

Рейтинг:
2

Richard Deeming

Если вы используете JSON.NET[^], вы можете использовать пользовательский конвертер для сопоставления вашего свойства со словарем:

public sealed class ArrayToDictionaryConverter : JsonConverter<Dictionary<long, long>>
{
    public override void WriteJson(JsonWriter writer, Dictionary<long, long> value, JsonSerializer serializer)
    {
        if (value is null)
        {
            writer.WriteNull();
            return;
        }
        
        writer.WriteStartArray();
        foreach (var pair in value)
        {
            writer.WriteStartArray();
            writer.WriteValue(pair.Key);
            writer.WriteValue(pair.Value);
            writer.WriteEndArray();
        }
        writer.WriteEndArray();
    }
    
    public override Dictionary<long, long> ReadJson(JsonReader reader, Type objectType, Dictionary<long, long> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var result = existingValue ?? new Dictionary<long, long>();
        long[][] array = serializer.Deserialize<long[][]>(reader);
        if (array != null)
        {
            for (int index = 0; index < array.Length; index++)
            {
                long[] pair = array[index];
                if (pair != null && pair.Length == 2)
                {
                    long key = pair[0];
                    long value = pair[1];
                    result[key] = value;
                }
            }
        }
        
        return result;
    }
}
Использование:
public sealed class Root
{
    [JsonProperty("values")]
    [JsonConverter(typeof(ArrayToDictionaryConverter))]
    public Dictionary<long, long> Values { get; set; }
}

string json = ...;
Root parsedValue = JsonConvert.DeserializeObject<Root>(json);
Dictionary<long, long> values = parsedValue.Values;

Вы также можете сделать что-то подобное с новым System.Text.Json библиотеки:
Как написать пользовательские конвертеры для сериализации JSON - .NET | Microsoft Docs[^]


Maciej Los

5ed!

Рейтинг:
2

George Swan

Если ваша строка имеет фиксированный формат, вы можете попробовать что-то вроде этого. Во-первых, обрезайте свою строку, удалите, {"values":[[ с самого начала и ]]} с конца. Тогда делай что-нибудь в этом роде.


Dictionary<long, int> testDict = new Dictionary<long, int>();
 string trimmed = "1298937600000,1],[1459468800000,16],[1462060800000,527],[1464739200000,173";
 var pairs = trimmed.Split("],[");
 foreach(var p in pairs)
 {
     var t = p.Split(',');
     testDict.Add(long.Parse(t[0]), int.Parse(t[1]));
 }
 //An alternative using fluent syntax
 var dictionary = trimmed.Split("],[").Select(s =>
  (Stamp: long.Parse(s.Substring(0, s.IndexOf(","))),
  Value: int.Parse(s.Substring(s.IndexOf(",") + 1)))
  ).ToDictionary(t => t.Stamp, t => t.Value);