Разобрать JSON со специальным символом и массивом с помощью antlr StringTemplate

У меня есть JSON от стороннего веб-сервиса, как показано ниже:

{
  "positions": {
    "587007777": {
      "company~": {
        "industries~": [
          {
            "name": {
              "localized": {
                "en_US": "Computer Software"
              }
            },
            "id": 4
          }
        ]
      },
      "company": "urn:li:organization:2252038",
      "localizedCompanyName": "Some company TEST2",
      "localizedTitle": "Sr. Engineer"
    },
    "587008888": {
      "company~": {
        "industries~": [
          {
            "name": {
              "localized": {
                "en_US": "Computer Software"
              }
            },
            "id": 4
          }
        ]
      },
      "company": "urn:li:organization:2258451",
      "localizedCompanyName": "Some company TEST",
      "localizedTitle": "Project Manager"
    }
  }
}

Я использую antlr4 stringtemplate для создания текстового вывода, как показано ниже:

Positions:

position 1
Title: Sr. Engineer
Company: Some company TEST2
Industry: Computer Science

position 2
Title: Project Manager
Company: Some company TEST
Industry: Computer Science

Шаблон Antlr:

$profile.positions:{it|$if(it.localizedTitle)$
Position $i$:
$if(it.localizedTitle)$Position: $it.localizedTitle$$endif$
$if(it.localizedDescription.rawText)$Summary: $it.localizedDescription.rawText$$endif$
$if(it.startMonthYear)$Start Date: $if(it.startMonthYear.month && it.startMonthYear.year)$$it.startMonthYear.month;format="month=toString"$, $endif$$it.startMonthYear.year$$endif$
$if(it.endMonthYear)$End Date: $if(it.endMonthYear.month && it.endMonthYear.year)$$it.endMonthYear.month;format="month=toString"$, $endif$$it.endMonthYear.year$$endif$
$if(it.localizedCompanyName)$Company: $it.localizedCompanyName$$endif$
Industry:$it.company~.industries~:{it|$if(it.name.localized.en_US)$
$if(it.name.localized.en_US)$ind: $it.name.localized.en_US$$endif$
$endif$}$

$endif$}$

Код C#:

string[] _arrayPropertyNames=new string[] {"skills","positions", "industries~" };
    public object GetProperty(Interpreter interpreter, TemplateFrame frame, object obj, object property, string propertyName)
            {
                Dictionary<string, object> dictionary = obj as Dictionary<string, object>;

                if (dictionary == null)
                {
                    throw new Exception("Can not convert parameters to dictionary");
                }
                try
                {
                    Debug.WriteLine("=>  properyname={0}, property={1} obj={2}", propertyName, property,
                        string.Join(",\r\n    -> ", dictionary.Select(m => m.Key + ":" + m.Value).ToArray()));
                }
                catch { }

                object resp = dictionary.ContainsKey(propertyName) ? dictionary[propertyName] : null;

                if (resp is JObject)
                {
                    if (_arrayPropertyNames.Contains(property)) // I want to avoid this check
                        return
                            ((JObject) resp).Children()
                                .Select(item => item.First().ToObject<Dictionary<string, object>>())
                                .ToList();

                    return JObject.FromObject(resp).ToObject<IDictionary<string, object>>();
                }

                JArray jArrayResponse = resp as JArray;

                if (jArrayResponse != null)
                {
                    if (jArrayResponse.Count == 0) return null;

                    List<JObject> elements = jArrayResponse.Children().OfType<JObject>().ToList();
                    if (elements.Any())
                    {
                        return elements.Select(item => item.ToObject<Dictionary<string, object>>()).ToList();
                    }

                    return jArrayResponse.Children().Select(item => item.Value<string>()).ToList();
                }

                return (resp != null && string.IsNullOrEmpty(resp.ToString())) ? null : resp;
            }

Я пытаюсь получить строку вывода с помощью antlr4, и у меня есть две проблемы:

  1. Позиции имеют тип массива, но в другом формате (так как они не имеют большой скобки). В коде я пытаюсь проверить, является ли элемент JSON JObject или JArray. Так как позиции имеют тип массива, я ожидал, что это будет JArray, но на самом деле это просто JObject. Итак, я должен поддерживать список _arrayPropertyNames для хранения списка имен свойств типа массив типа и обрабатывать его, чтобы получить дочерние элементы. Я хочу избежать этого жесткого кода и получить общее решение.
  2. Второй - это JSON, содержащий имя свойства "company~", которое имеет ~ в конце. И есть еще одно свойство, имя которого просто "company" по тому же пути, но нам просто нужно получить отраслевое имя из элемента "company~", поэтому в шаблоне antlr4 мы определили, как указано выше. Но мы получаем просто "company" в propertyName в методе GetProperty, но словарь (obj) содержит "company~" в качестве ключа, поэтому не может извлечь отрасль.

0 ответов

Другие вопросы по тегам