В моем текущем проекте я настраиваю утилиту для сравнения полей, созданных любым количеством версий приложения, с последними результатами приложения. Например, если я отправлю документ, содержащий «Это тест системы аварийного вещания», рабочая версия приложения может вернуть что-то вроде:
Образец A:
`{
text: "This is a test of the emergency broadcast system",
numWords: 9
}`
Последняя стабильная версия разработки может выплевывать:
Образец B:
`{
text: "This is a test of the emergency broadcast system",
numWords: 9,
notes: [ "Emergency", "Urgent"],
}`
А последняя сборка может дать что-то вроде:
Образец C:
`{
text: "This is a test of the emergency broadcast system",
numWords: 9,
notes: [ "Emergency", "Urgent"],
subSentences: [
sentence1: { text: "This is a test.",
numWords: 4 }
]
}`
Утилита хранит то, что она ожидает от приложения, и структуру, которая содержит A) поле, которое она пытается сравнить, и B) список этих структур, содержащих любые подполя. Например, я хотел бы убедиться, что text
каждого subSentence
совпадает. Я могу сделать это, если знаю название каждого поля, но ...
Проблема в том, что для поддержки расширяемости программное обеспечение использует protobuf, а я должен использовать отражение. Я не могу делать никаких предположений относительно содержимого любого объекта, который приложение возвратит. Единственная информация, которая у меня есть, это список имен полей. Если бы я хотел убедиться, что последняя сборка получает правильное numWords
для всего предложения, например, я бы передал утилите объект, предоставленный приложением, и список строк, содержащих запись numWords.
Это создает две проблемы:
EqualsBuilder
, предоставляемый общими Apache (версия 3.9 на момент написания этой статьи) проверяет каждое поле по умолчанию. В моем случае это бесполезно, потому что, если я ожидаю образец A и проверяю только numWords
и текст, утилита должна его пропустить. Но EqualsBuilder.reflectEquals(Sample A, Sample B)
не вернет true, поскольку в образце B есть совершенно новое поле.
EqualsBuilder предоставляет .append()
методы для сравнения только указанных полей, что звучит больше, чем мне нужно ... за исключением вложенных объектов данных. API поддерживает только добавление общих типов, поэтому я легко могу проверить numWords
, выполнив EqualsBuilder.append(9).isEqual(Sample A)
, но нет способа сделать что-то вроде EqualsBuilder.append(subSentence)
и использовать это для сравнения.
Итак, я думаю, что мой вопрос сводится к следующему: есть ли способ сравнить поля, основанные на полях имена вместо значений полей? А если нет, есть ли способ вытащить внутренние структуры, ничего не зная о них (кроме того, что они существуют)?