https://www.newtonsoft.com/json
если вам предложат регулярки, стоит сравнивать производительность (регулярки не блещут скоростью
upd все верно, простотой тоже, тривиальные случаи не считаем )))
сам бы скорее всего сделал в рукопашку, при условии что другие данные точно не нужны. при чем суть вы уже описали ;))) и по производительности, это наверняка самый быстрый вариант (
upd )по производительности, а вот по реализации - зависит от навыков, кому то может быть проще newtonsoft (ну и см
ленивый вариант, там тоже не производительность (но думаю и далеко не самый тормозной), но легко быстро набросать логику и легко ее оттестировать)
ps можно еще ленивый вариант -
Split по
{"userId":"
тогда первый элемент отбрасываем, все остальные начинаются с искомой величины, надо только хвост
"} bla-bla-bla
отрубить
ps держите прототип, содержит все 3 упомянутые подхода, но перфоманс можно сравнить только на реально больших данных )).. (но на больших данных могут и баги полезть ;)
spoiler
вопрос понравился, и выдалось время.. хотя и не за 15 минут, врать не буду,
часа полтора порядка 45 минут ушло на заковырки )) в основном с json (мало опыта)
upd и уже исправлено - была заготовка класса для частичной json выборки, но она не нужна
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace parsejson111
{
class Program
{
const string data = "{\"anchor\":\"aaabbbccc==\",\"members\":[{\"userId\":\"111\"},{\"userId\":\"2222\"},{\"userId\":\"333\"},{\"userId\":\"444\"}],\"has_more\":true}";
// фишки замера заложены, но разница может проявиться только на больших объемах ))
static void Main(string[] args)
{
Console.WriteLine("data:");
Console.WriteLine(data);
var sw = new Stopwatch();
sw.Start();
var ts = sw.Elapsed; // лень объявлять тип
json();
hand();
lazy();
sw.Stop();
Console.WriteLine("press any key to continue...");
Console.ReadKey();
void json() // возможно существует более элегантный вариант. тут у меня опыта мало ))
{
sw.Reset();
Console.WriteLine("... json");
var j = JObject.Parse(data);
var r = j["members"].Children().ToList();
foreach (var u in r)
{
var uid = JObject.Parse(u.ToString());
var id = uid["userId"].Value<string>();
Console.WriteLine(id);
}
ts = sw.Elapsed;
Console.WriteLine($"\t{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Milliseconds:000}");
}
void hand() // зато тут гарантирую - оптимизировать лучше не реально, и по перфомансу вряд ли можно лучше ))
{
sw.Reset();
Console.WriteLine("... hand");
var p = 0;
while ((p = data.IndexOf("{\"userId\":\"", p)) > 0)
{
p += 11; //длина шаблона. заодно избегаем риска зацикливания
var f = data.IndexOf("\"}", p);
Console.WriteLine(data.Substring(p, f - p));
}
ts = sw.Elapsed;
Console.WriteLine($"\t{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Milliseconds:000}");
}
void lazy()
{
sw.Reset();
Console.WriteLine("... lazy");
var t = data.Split(new string[] { "{\"userId\":\"" }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 1; i < t.Length; i++) // здесь и везде - обработка пустого множества на вашей совести
{
var id = t[i].Split(new string[] { "\"}" }, StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine(id[0]);
}
ts = sw.Elapsed;
Console.WriteLine($"\t{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Milliseconds:000}");
}
}
}
}