BigBear.ai
  • Home
  • Industries
    • Academia
    • Government
    • Healthcare
    • Manufacturing
  • Solutions
    • Cyber
    • Data Analytics
    • Enterprise Planning and Logistics
    • Intelligent Automation
    • Modeling Solutions
    • Professional Services
  • Company
    • About
    • Investor Relations
    • Partners
    • Team
  • Careers
    • Benefits
    • Culture
    • Explore Jobs
    • Military and Veterans
    • Applicant Login
    • Employee Login
  • Resources
    • Blog
    • Events
    • Newsroom
    • Resource Library
    • Online Store
  • Contact
Search

Home Technology Dynamically Parsing JSON to Arbitrary Java Classes using the Jackson JSON Library

Blog

Dynamically Parsing JSON to Arbitrary Java Classes using the Jackson JSON Library

Paul Wisneskey
June 24, 2020
  • Share
  • Share

In our advanced predictive analytics platform, we’ve built some very innovative techniques that let users model aggregated data using arbitrary grouping of target entities and weighted measures synthesized from the underlying source data. For example, a user can define a weighted measure called “financial stability” that is a weighted combination various financial measures of a country (such as GDP, debt ratio, exports, etc.) Furthermore, the user can then apply this measure across a composite entity such as the G20 countries and build a model for a question such as “what happens when the financial stability of the G20 drops by 20%?”

The system is able to translate this back to the underlying measures spread across all of the countries that make up the G20 and then build the predictive model to answer the question.  The results can then also be aggregated back up to the country groupings so we can show the user the effect on the other measures for the G20 as a whole. This makes it significantly easier for an analyst to build sweeping models without having to individually adjust a daunting number of underlying measure values.

In order to support this capability, we’ve built a sophisticated query engine that sits on top of ElasticSearch. The query engine accepts a high-level query that may be for composite entities and synthetic measures and breaks it down into very complex ElasticSearch queries for all of the individual value which aggregating and filtering them as needed to support the high-level query’s requirements.

This query returns the average value of the synthesized measure “Financial Stability” sorted from lowest to highest for the three specified countries over the given date period.

Since we have what is effectively a dynamic query language, we did not want to have to develop a full-scale parser for it. Instead, we decided to develop a set of query classes and use the Jackson JSON library to parse an incoming query string into the appropriate query class based on the type of query.

Usually, to do this in Jackson you would use its type annotations to map from a base class into the appropriate subclass based on a property in the JSON.

Unfortunately, this technique means you have to include a property in the JSON (queryType in this case) which makes it not as obvious what kind of query is being run.

This was not very intuitive and did not feel natural for a query language, particularly when multiple queries were being submitted in a batch. We really wanted the query type to be the top element (as in the first JSON example). To do this, we needed to develop a custom deserializer that could map from a top level JSON property to the appropriate query subclass. This turned out to be quite simple and we were even able to leverage the existing Jackson annotations for configuring in from the base class.

When it initializes, the custom typed deserializer will use the @JsonSubTypes annotation on the Query class to determine all of the possible query subclasses that an incoming JSON query request can be parsed into.

Finally, actually parsing an incoming query string is very straightforward.

With thoughtful composition of the Query class hierarchy to support common query elements such as filters and result sort orders, this parsing technique provides an easy way to support a very sophisticated query syntax while leveraging the Jackson JSON library to handle all the heavy lifting of parsing the incoming queries. In our Middleware, we accept the query as the body of a POST request which gives us the string to pass into the parser. This makes for a very clean API that easily extensible; to add a new query type, we just implement a new subclass and register it in the @JsonSubypes annotation of the base query class.

Posted in Data Modeling, Technology.
BigBear.ai
  • Home
  • Industries
  • Solutions
  • Company
  • Careers
  • Blog
  • Investor Relations
  • Contact
  • Twitter
  • Facebook
  • Linkedin
  • Google My business for BigBear.ai
1-410-312-0885
[email protected]
  • Privacy Policy
  • Terms of Use
  • Accessibility
  • Site Map
© BigBear.ai 2023
We value your privacy
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.
Privacy Policy | Do not sell my personal information
AcceptCookie Settings
Manage Consent

Cookies Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
CookieDurationDescription
cookielawinfo-checkbox-analytics11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional11 monthsThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
JSESSIONIDsessionThe JSESSIONID cookie is used by New Relic to store a session identifier so that New Relic can monitor session counts for an application.
viewed_cookie_policy11 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
CookieDurationDescription
__atuvc1 year 1 monthAddThis sets this cookie to ensure that the updated count is seen when one shares a page and returns to it, before the share count cache is updated.
__atuvs30 minutesAddThis sets this cookie to ensure that the updated count is seen when one shares a page and returns to it, before the share count cache is updated.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
CookieDurationDescription
_ga2 yearsThe _ga cookie, installed by Google Analytics, calculates visitor, session and campaign data and also keeps track of site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognize unique visitors.
_ga_NK4L4Q320Q2 yearsThis cookie is installed by Google Analytics.
_gat_gtag_UA_163894009_21 minuteSet by Google to distinguish users.
_gid1 dayInstalled by Google Analytics, _gid cookie stores information on how visitors use a website, while also creating an analytics report of the website's performance. Some of the data that are collected include the number of visitors, their source, and the pages they visit anonymously.
at-randneverAddThis sets this cookie to track page visits, sources of traffic and share counts.
CONSENT2 yearsYouTube sets this cookie via embedded youtube-videos and registers anonymous statistical data.
uvc1 year 1 monthSet by addthis.com to determine the usage of addthis.com service.
Advertisement
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
CookieDurationDescription
f5avraaaaaaaaaaaaaaaa_session_sessionbusinesswire.com cookie
loc1 year 1 monthAddThis sets this geolocation cookie to help understand the location of users who share the information.
VISITOR_INFO1_LIVE5 months 27 daysA cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface.
YSCsessionYSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages.
yt-remote-connected-devicesneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
yt-remote-device-idneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
Save & Accept