跪拜 Guibai
← All articles
Android · Kotlin · AI Programming

Rebuilding JSON from 4KB logcat shards when encryption breaks packet capture

By 红尘伴蝶舞 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Generic JSON tools assume a complete, valid document, which Android logcat never provides. Without a purpose-built parser, developers debugging encrypted APIs either hand-type dozens of fields or settle for corrupted JSON from the ring buffer.

Summary

Android's network interceptors encrypt request bodies and decrypt responses, so packet capture tools like Charles see only base64 ciphertext. The one place the real JSON ever appears is a logcat line that gets truncated at 4KB, overridden in the middle by the ring buffer, and prefixed with timestamp, pid, and package name. A developer built a single-file HTML tool that strips those prefixes, reassembles the fragments, and generates Kotlin data classes with Gson or kotlinx annotations in about ten seconds per interface.

The first AI-written version handled the obvious cases: seven prefix formats, bracket and quote balancing, and permissive parsing for trailing commas and single quotes. Real logs broke it three times. A permissive parser ate the next field's first letter when protobuf TextFormat had no commas. Ring buffer overflow dropped a middle segment, leaving `pe` as a field name. The fix relies on token-boundary detection and realignment to the first `],"`, which restored a 74-field object to 111 fields, losing only the one that fell into the dropped chunk.

The author set a simple rule: if a task happens more than five times a week, it's worth a half hour with AI to build a tool. The parser functions are DOM-free, so they can be lifted into a CLI or Android Studio plugin. The tool's own limits are explicit: no real field names without a .proto, no recovery for missing chunks, no enumeration inference.

Takeaways
— The tool is a single HTML file, offline, zero dependencies; double-click runs it in a browser.
— It recognizes seven logcat prefix formats, matching by information richness, and reassembles fragments only when the previous line is unclosed.
— A custom recursive descent parser replaces JSON.parse because JavaScript loses precision beyond 2^53-1, which silently corrupts 19-digit order IDs.
— Three real-log bugs: swallowed newlines in multi-line protobuf, a permissive parser eating the next field's initial letter on missing commas, and ring buffer overflow dropping a middle JSON segment.
— The realignment fix uses the first `],"` or `]}` to rejoin after a lost segment; it restored `activity` from 74 to 111 fields, losing only `rankBadges`.
— Kotlin type-name collisions are handled with a blacklist that suffixes Item to List, Map, String, Activity, View, Fragment, Context, and Intent.
— Nullability has three modes, with all-nullable as default because per-sample inference would crash in production when a field disappears.
— The parser functions parseLog, parseLoose, typeOf, genKotlin have zero DOM dependencies and can be reused in a CLI or Android Studio plugin.
Conclusions

AI wrote the regex, parser, and type mapping in one shot, but every failure came from domain knowledge absent from the requirements: the ring buffer drops the middle, not the tail, and protobuf TextFormat has no commas.

The status bar reporting '10 concatenations, 1 missing place skipped' is the real diagnostic aid; silent guessing would have hidden the tool's incomplete recovery.

AI changes the break-even for writing personal tools: a half-hour to first version means a daily five-minute loss becomes worth automating immediately, even for one developer.

Concepts & terms
logcat ring buffer
Android's logcat is a circular buffer; when it fills, oldest entries are overwritten. A long log line can lose a middle section, not just the end, because the write pointer wraps around.
OkHttp interceptor
An OkHttp interceptor can transform HTTP requests and responses; here it encrypts request bodies and decrypts responses, which makes packet capture show only ciphertext.
Safe integer
In JavaScript, Number is double-precision float; integers above 2^53-1 lose precision silently, so JSON.parse can mangle large IDs without throwing an error.
Recursive descent parser
A top-down parser where each grammar rule is a function that consumes the input directly; the author wrote one to preserve exact number strings and infer Int vs Long.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗