Skip to content

Split JSON tidying into core parser and tibblify wrapper - #96

Merged
jonthegeek merged 3 commits into
mainfrom
copilot/resp-tidy-json-vs-resp-tidy-json-tibblify
Jun 7, 2026
Merged

Split JSON tidying into core parser and tibblify wrapper#96
jonthegeek merged 3 commits into
mainfrom
copilot/resp-tidy-json-vs-resp-tidy-json-tibblify

Conversation

Copilot AI commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

resp_tidy_json() previously always tibblified output, which made it unsuitable for simple non-tabular JSON payloads. This PR separates concerns by introducing a plain JSON tidier and moving tibblify behavior into an explicit companion API.

  • API split: base JSON vs tibblify JSON

    • Added new base functions:
      • resp_tidy_json(resp, subset_path = NULL, simplifyVector = FALSE)
      • tidy_policy_json(subset_path = NULL, simplifyVector = FALSE)
    • Renamed former tibblifying functions to:
      • resp_tidy_json_tibblify()
      • tidy_policy_json_tibblify()
  • Behavior changes

    • resp_tidy_json() now:
      • parses via httr2::resp_body_json()
      • supports and forwards simplifyVector
      • applies subset_path
      • returns parsed result directly (or NULL if empty)
      • no longer accepts spec / unspecified
    • resp_tidy_json_tibblify() now delegates JSON extraction to resp_tidy_json(..., simplifyVector = FALSE) and only performs tibblify-specific steps (check_installed, tibblify()).
  • Docs and usage updates

    • Split source/test files to match function families:
      • R/resp_tidy_json.R
      • R/resp_tidy_json_tibblify.R
      • tests/testthat/test-resp_tidy_json.R
      • tests/testthat/test-resp_tidy_json_tibblify.R
    • Regenerated Rd/NAMESPACE exports for new names.
    • Updated examples that expect tibble output to use tidy_policy_json_tibblify().
  • Example

    # raw parsed JSON (no tibblify)
    resp_tidy_json(resp, subset_path = c("message", "items"), simplifyVector = FALSE)
    
    # tibble-oriented parsing via explicit wrapper
    resp_tidy_json_tibblify(resp, subset_path = c("message", "items"))

Copilot AI linked an issue Jun 7, 2026 that may be closed by this pull request
Co-authored-by: jonthegeek <33983824+jonthegeek@users.noreply.github.com>
Copilot AI changed the title [WIP] Rename resp_tidy_json and create simpler resp_tidy_json function Split JSON tidying into core parser and tibblify wrapper Jun 7, 2026
Copilot AI requested a review from jonthegeek June 7, 2026 14:59
@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

{qcthat} Report: User Acceptance

No issues are awaiting UAT.

This report was generated by this GitHub Actions job.

Last updated: 2026-06-07 16:13:30 UTC

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

{qcthat} Reports

PR-Associated Issues

✅ A qcthat issue test matrix with 1 milestone, 1 issue, and 13 tests
└─█─Milestone: 0.1 (1 issue, 13 tests)
  └─📥─Feature 95: `resp_tidy_json()` vs `resp_tidy_json_tibblify()`
    ├─✅─resp_tidy_json_tibblify fails gracefully with a bad subset_path (#40, #95)
    ├─✅─resp_tidy_json_tibblify returns NULL for an empty body (#40, #95)
    ├─✅─resp_tidy_json_tibblify tidies a response (#40, #95)
    ├─✅─resp_tidy_json_tibblify subsets a response (#40, #95)
    ├─✅─resp_tidy_json_tibblify tidies a response with a spec (#40, #95)
    ├─✅─resp_tidy_json_tibblify calls resp_tidy_json with simplifyVector = FALSE (#40, #95)
    ├─✅─tidy_policy_json_tibblify() prepares parser for resp_tidy() (#40, #95)
    ├─✅─resp_tidy_json fails gracefully with a bad subset_path (#95)
    ├─✅─resp_tidy_json returns NULL for an empty body (#95)
    ├─✅─resp_tidy_json returns parsed JSON directly (#95)
    ├─✅─resp_tidy_json subsets a response (#95)
    ├─✅─resp_tidy_json passes simplifyVector to httr2::resp_body_json (#95)
    └─✅─tidy_policy_json() prepares parser for resp_tidy() (#95)
# Issue state: 📥 = open, ☑️ = closed (completed), ⛔ = closed (won't fix)
# Test disposition: ✅ = passed, ❌ = failed, 🚫 = skipped
✅ All tests passed

🟢 All issues have at least one test


Completed Issues

✅ A qcthat issue test matrix with 1 milestone, 18 issues, and 91 tests
├─█─Milestone: 0.1 (17 issues, 88 tests)
│ ├─☑️─Feature 92: `header` and `cookie` params in `req_modify()` and `req_prepare()`
│ │ ├─✅─req_modify() applies headers (#92)
│ │ ├─✅─req_modify() uses NULL headers to remove previously-set headers (#92)
│ │ ├─✅─req_modify() applies cookies (#92)
│ │ ├─✅─req_modify() removes NULL cookies (#92)
│ │ ├─✅─req_prepare() applies headers (#92)
│ │ ├─✅─req_prepare() uses NULL headers to remove previously-set headers (#92)
│ │ ├─✅─req_prepare() applies cookies (#92)
│ │ └─✅─req_prepare() removes NULL cookies (#92)
│ ├─☑️─Feature 30: Simpler cookies in req_auth_api_key()
│ │ └─✅─req_auth_api_key works for cookies (#30)
│ ├─☑️─Feature 29: User Agent Modifier
│ │ ├─✅─req_pkg_user_agent adds a package agent (#29)
│ │ ├─✅─req_pkg_user_agent adds a package agent and url (#29)
│ │ ├─✅─Corner case of no supplied name works (#29)
│ │ ├─✅─Corner case of no supplied agent works (#29)
│ │ └─✅─req_prepare() applies user agent (#10, #29)
│ ├─☑️─Feature 19: Export more autoreq pieces
│ │ ├─✅─req_prepare() uses query parameters (#5, #10, #11, #19)
│ │ ├─✅─req_prepare() uses the .multi arg (#5, #11, #19)
│ │ ├─✅─req_prepare() removes empty query parameters (#5, #11, #19)
│ │ └─✅─req_prepare() applies methods (#5, #10, #11, #19)
│ ├─☑️─Feature 11: Reconcile body parser
│ │ ├─✅─req_prepare() uses query parameters (#5, #10, #11, #19)
│ │ ├─✅─req_prepare() uses the .multi arg (#5, #11, #19)
│ │ ├─✅─req_prepare() removes empty query parameters (#5, #11, #19)
│ │ ├─✅─req_prepare() applies methods (#5, #10, #11, #19)
│ │ └─✅─resp_parse works for raw results (#11)
│ ├─☑️─Feature 10: Split call_api()
│ │ ├─✅─req_prepare() applies user agent (#10, #29)
│ │ ├─✅─req_prepare() deals with paths (#10)
│ │ ├─✅─req_prepare() uses query parameters (#5, #10, #11, #19)
│ │ ├─✅─req_prepare() uses body parameters (#10)
│ │ ├─✅─req_prepare() applies methods (#5, #10, #11, #19)
│ │ ├─✅─resp_parse parses json-containing httr2_response objects (#10)
│ │ ├─✅─resp_parse parses httr2_response objects with specified parser (#10)
│ │ ├─✅─resp_parse returns raw resp if NULL parser specified (#10)
│ │ ├─✅─resp_parse accepts parser args (#10)
│ │ └─✅─resp_parse parses lists of httr2_responses (#10)
│ ├─☑️─Feature 8: Authenticate with API Keys
│ │ ├─✅─req_auth_api_key works for header (#8)
│ │ └─✅─req_auth_api_key works for query (#8)
│ ├─☑️─Feature 6: Standardize endpoint argument
│ │ └─✅─bodies with paths are handled properly (#6)
│ ├─☑️─Feature 5: req_perform() args
│ │ ├─✅─req_prepare() uses query parameters (#5, #10, #11, #19)
│ │ ├─✅─req_prepare() uses the .multi arg (#5, #11, #19)
│ │ ├─✅─req_prepare() removes empty query parameters (#5, #11, #19)
│ │ └─✅─req_prepare() applies methods (#5, #10, #11, #19)
│ ├─☑️─Bug 90: Clean up `resp_parse()`
│ │ ├─✅─resp_parse drops NULL parsed pages before combining (#90)
│ │ └─✅─resp_parse returns NULL when all parsed pages are NULL (#90)
│ ├─☑️─Feature 86: `tidy_policy_prepare()` function
│ │ ├─✅─req_prepare() applies prepared tidying (#86)
│ │ ├─✅─req_prepare() errors for unsupported tidy policy objects (#86)
│ │ ├─✅─req_tidy_policy applies resp_body_auto by default (#44, #86)
│ │ ├─✅─req_tidy_policy applies the specified policy (#44, #86)
│ │ ├─✅─tidy_policy_body_auto() prepares resp_body_auto for resp_tidy() (#86)
│ │ ├─✅─tidy_policy_unknown() prepares resp_tidy_unknown for resp_tidy() (#86)
│ │ ├─✅─tidy_policy_prepare() constructs nectar_tidy_policy objects (#86)
│ │ ├─✅─.as_nectar_tidy_policy() returns nectar_tidy_policy objects unchanged (#86)
│ │ ├─✅─.as_nectar_tidy_policy() returns NULL for NULL input (#86)
│ │ ├─✅─.as_nectar_tidy_policy() errors for list without tidy_fn (#86)
│ │ ├─✅─.as_nectar_tidy_policy() converts function input to nectar_tidy_policy (#86)
│ │ ├─✅─.as_nectar_tidy_policy() merges tidy_args with additional tidy policy fields (#86)
│ │ └─✅─.as_nectar_tidy_policy() errors for non-listable tidy_args (#86)
│ ├─☑️─Feature 81: `auth_prepare()` function
│ │ ├─✅─auth_prepare() constructs nectar_auth objects (#81)
│ │ ├─✅─.as_nectar_auth() returns nectar_auth objects unchanged (#81)
│ │ ├─✅─.as_nectar_auth() returns NULL auth_fn and empty auth_args for NULL input (#81)
│ │ ├─✅─.as_nectar_auth() errors for list without auth_fn (#81)
│ │ ├─✅─.as_nectar_auth() converts function input to nectar_auth (#81)
│ │ ├─✅─.as_nectar_auth() merges auth_args with additional auth fields (#81)
│ │ ├─✅─.as_nectar_auth() errors for non-listable auth_args (#81)
│ │ ├─✅─auth_api_key() prepares req_auth_api_key auth (#81)
│ │ ├─✅─req_prepare() applies prepared auth (#81)
│ │ └─✅─req_prepare() errors for unsupported auth objects (#81)
│ ├─☑️─Bug 76: Remove api key on `NULL`
│ │ ├─✅─req_auth_api_key returns req unchanged if api_key is NA or empty (#76)
│ │ └─✅─req_auth_api_key removes the key when api_key is NULL (#76)
│ ├─☑️─Feature 44: resp_tidy policies
│ │ ├─✅─req_tidy_policy applies resp_body_auto by default (#44, #86)
│ │ └─✅─req_tidy_policy applies the specified policy (#44, #86)
│ ├─☑️─Feature 40: resp_tidy()
│ │ ├─✅─resp_body_auto works for json (#40)
│ │ ├─✅─resp_body_auto works for xml (#40)
│ │ ├─✅─resp_body_auto works for html (#40)
│ │ ├─✅─resp_body_auto works for svg (#40)
│ │ ├─✅─resp_body_auto works for csv (#40)
│ │ ├─✅─resp_body_auto works for tsv (#40)
│ │ ├─✅─resp_body_auto works for json subtypes (#40)
│ │ ├─✅─resp_body_auto works for other strings (#40)
│ │ ├─✅─resp_body_auto works for other things (#40)
│ │ ├─✅─resp_body_csv extracts csv data (#40)
│ │ ├─✅─resp_body_csv fails gracefully for bad data (#40)
│ │ ├─✅─resp_body_tsv extracts tsv data (#40)
│ │ ├─✅─resp_body_tsv fails gracefully for bad data (#40)
│ │ ├─✅─resp_body_separate listifies responses (#40)
│ │ ├─✅─resp_parse fails gracefully for unsupported classes (#40)
│ │ ├─✅─resp_tidy_json_tibblify fails gracefully with a bad subset_path (#40, #95)
│ │ ├─✅─resp_tidy_json_tibblify returns NULL for an empty body (#40, #95)
│ │ ├─✅─resp_tidy_json_tibblify tidies a response (#40, #95)
│ │ ├─✅─resp_tidy_json_tibblify subsets a response (#40, #95)
│ │ ├─✅─resp_tidy_json_tibblify tidies a response with a spec (#40, #95)
│ │ ├─✅─resp_tidy_json_tibblify calls resp_tidy_json with simplifyVector = FALSE (#40, #95)
│ │ ├─✅─tidy_policy_json_tibblify() prepares parser for resp_tidy() (#40, #95)
│ │ ├─✅─resp_tidy parses json-containing httr2_response objects (#40, #88)
│ │ ├─✅─resp_tidy parses httr2_response objects with resp_tidy policy (#40, #88)
│ │ └─✅─resp_tidy uses policies$resp_tidy$tidy_args (#40, #88)
│ ├─☑️─Feature 35: req_pagination()
│ │ ├─✅─req_pagination_policy errors informatively for bad fn (#35)
│ │ ├─✅─req_pagination_policy applies the specified policy (#35)
│ │ ├─✅─choose_pagination_fn returns NULL for no policy (#35)
│ │ └─✅─choose_pagination_fn extracts the pagination_fn (#35)
│ └─☑️─Feature 32: Feature: smarter cursor pagination
│   ├─✅─iterate_with_json_cursor repeats with non-empty cursor (#32)
│   ├─✅─iterate_with_json_cursor stops with NULL cursor (#32)
│   └─✅─iterate_with_json_cursor stops with blank cursor (#32)
└─█─Milestone: <none> (1 issue, 6 tests)
  └─☑️─Issue 88: Clarify `resp_parse()` vs `resp_tidy()`
    ├─✅─resp_parse fails gracefully for list of non-responses (#88)
    ├─✅─resp_tidy returns NULL for NULL input (#88)
    ├─✅─resp_tidy errors for non-response input (#88)
    ├─✅─resp_tidy parses json-containing httr2_response objects (#40, #88)
    ├─✅─resp_tidy parses httr2_response objects with resp_tidy policy (#40, #88)
    └─✅─resp_tidy uses policies$resp_tidy$tidy_args (#40, #88)
# Issue state: 📥 = open, ☑️ = closed (completed), ⛔ = closed (won't fix)
# Test disposition: ✅ = passed, ❌ = failed, 🚫 = skipped
✅ All tests passed

🟢 All issues have at least one test

🙈 7 issues with label "qcthat-nocov" were ignored


This report was generated by this GitHub Actions job.

Last updated: 2026-06-07 16:13:31 UTC

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🌐 PR pkgdown deployed

This report was generated by this GitHub Actions job.

Last updated: 2026-06-07 16:13:54 UTC

@jonthegeek jonthegeek left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address these change requests.

Comment thread R/resp_tidy_json.R Outdated
Comment thread R/resp_tidy_json.R Outdated
Comment thread R/resp_tidy_json_tibblify.R Outdated
Comment thread nectar_0.0.0.9007.tar.gz Outdated
Comment thread tests/testthat/test-resp_tidy_json_tibblify.R
Comment thread vignettes/nectar.Rmd
Co-authored-by: jonthegeek <33983824+jonthegeek@users.noreply.github.com>

Copilot AI commented Jun 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address these change requests.

Addressed in 80ef569.

Updated the roxygen inheritance in R/resp_tidy_json.R, moved rlang::check_installed() inside the non-empty branch in resp_tidy_json_tibblify(), retagged tibblify tests as (#40, #95), and removed nectar_0.0.0.9007.tar.gz from the repo.

Copilot AI requested a review from jonthegeek June 7, 2026 15:23
@jonthegeek
jonthegeek marked this pull request as ready for review June 7, 2026 16:38
@jonthegeek
jonthegeek merged commit d27c4cb into main Jun 7, 2026
10 checks passed
@jonthegeek
jonthegeek deleted the copilot/resp-tidy-json-vs-resp-tidy-json-tibblify branch June 7, 2026 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

resp_tidy_json() vs resp_tidy_json_tibblify()

2 participants