JsonExtract.h header

#include <ew/app/JsonExtract.h>

Namespace ew::app

Enumerations

enum class JsonKind { Object, Array, Either }

The kind of top-level JSON value a caller expects, so extractFirstJsonValue can skip an embedded value of the wrong kind – e.g. a leading {...} note when an array of results is wanted.

Functions

QJsonDocument ew::app::extractFirstJsonValue(const QString &text, JsonKind wanted=JsonKind::Either)

Extracts the first complete, non-empty JSON value of kind wanted embedded in text, tolerating prose or code fences around it – and, unlike a naive first-bracket-to-last-bracket scan, trailing prose that itself contains brackets. It first tries to parse the whole trimmed text (the common case where the reply is pure JSON); failing that, it scans for a balanced {...}/[...] span (respecting quoted strings and escapes) that parses as JSON of kind wanted, preferring a non-empty container over an empty one so a leading []/{} decoy does not mask the real payload (it still returns an empty container if that is all there is – a legitimate "no results" reply). The scan work is bounded, so a pathological reply of many unbalanced brackets cannot make it quadratic. Returns a null QJsonDocument (isNull()) when no such value is present.

This backs the AI reply parsers: EntityExtraction passes JsonKind::Array and EntityDraft passes JsonKind::Object, which must be robust to the varied output of whatever bring-your-own model the user configures. Pure and unit-testable.

QString ew::app::jsonScalarToString(const QJsonValue &value)

Renders a scalar JSON value as the plain string a codex field stores: a string verbatim, an integral number without a decimal point (a year / age / population), a non-integral number in a compact form, and a bool as "true"/"false". A null, object, or array yields an empty string (it is not a scalar field value). Models routinely reply with a bare number or bool for a numeric field, which QJsonValue::toString() would otherwise silently drop as an empty string.