Skip to content

Base Class and Methods for 'gson' Format

1packages dependsuggested by 1
421.1Kdownloads / year
96.1%test coverage
13/13flavors OK

Overview

About

Provides a lightweight container and exchange format for gene set collections. A 'GSON' object stores which genes belong to which gene set, together with gene set and gene names, the identifier types in use, species, versions and source metadata. A collection can be built from data frames, read from and written to the 'gson' JavaScript Object Notation (JSON) format and the 'GMT' format, subset by gene set, merged across sources, validated, and resolved to the web addresses of the databases it comes from, so that a collection gathered by one package can be analysed by another.

Changes in 0.2.2
  • keep the documented columns of gsid2gene, gsid2name and gene2name as character in gson(), so that a producer passing a factor no longer leaks it into the object, and a double column is stored by its digits -- as.character(1e6) prints "1e+06", so format(scientific = FALSE) is used for doubles. clusterProfiler::gson_GO() builds gsid2gene with utils::stack(), whose ind column is a factor, and a factor retains the levels it no longer uses: every split(gsid2gene$gene, gsid2gene$gsid) then invents one empty gene set per unused level -- for gson_GO("org.Hs.eg.db", ont = "CC") that is 4069 gene sets of which 2067 are empty, although only 2002 terms carry annotations -- and length(), names(), write.gmt() and write.gson() report those phantom sets as real ones (write.gmt() emits a gsid<TAB>description line with no gene, write.gson() a "gsid": [] entry). The phantoms reach the consumers through their own split(): enrichit::ora_gson(), gsea_gson(), nsea_gson() and DOSE::getGeneSet(). write.gson()/read.gson() also stopped round-tripping to an identical object, since JSON has no factor type and read.gson() coerced the columns back to character; that coercion now lives in one place, gson(), and the duplicated lines in read.gson() are gone (2026-10-08, Thu)
  • check the structural contract of the three mapping tables when a GSON is created, so an object assembled with new("GSON", ...) is refused by validObject() when a table is not a data.frame, lacks the documented columns, or holds identifiers that are not character. Only the structure is enforced here: duplicated identifiers, missing cross-references between the tables, empty tables and non-scalar metadata stay with validate_gson(), which reports them instead of refusing them, and objects that violate those rules must remain constructible so that they can be inspected (2026-10-08, Thu)
  • write.gmt() and write.gson() now skip memberships that carry no gene set ID or no gene, and warn about how many were omitted. An empty gsid used to abort write.gmt() with subscript out of bounds, and a missing gene used to reach the output as the literal NA -- a GMT field of NA, a [null] member in the JSON -- which the consumers read back as a gene genuinely called NA and hand on to the enrichment routines. write.gmt() also falls back to the gene set ID when gsid2name holds no usable name for a set, so the description column can no longer be the string NA either. Objects whose memberships are all usable are written unchanged and silently, and write.gson()/read.gson() still round-trip them to an identical object (2026-10-08, Thu)
  • gson() also drops the row labels the producers leave on the three mapping tables, so that an object whose memberships are already grouped by gene set ID reads back from write.gson()/read.gson() as the object it was. clusterProfiler::gson_GO("org.Hs.eg.db", ont = "CC") rows its gsid2name by GO term and inherits for gsid2gene the row indices of the annotation table it was subset from, while JSON carries no row names and read.gson() can only produce the default sequence: identical() of the two objects was FALSE for that 2002-set, 378845-membership object even though every value matched, and it is TRUE now. The labels repeat what the columns already hold, so dropping them gives up nothing. What the format still cannot carry is the row order of gsid2gene, since a .gson file keys the memberships by gsid and a table that was not already grouped by gene set ID comes back regrouped -- the gene sets and the order of the genes within each are preserved (2026-10-08, Thu)
  • GSON gains gsidtype, the identifier domain the gene set IDs are drawn from (GO, KEGG, REAC, ...), so that a consumer can stop inferring it from the shape of the identifiers -- GOSemSim::parse_gson() currently repairs a missing GO: prefix and rejects a collection with no GO ID found by regular expression, which is exactly the guess this field replaces. It sits beside keytype, which describes the genes rather than the gene set IDs, and is threaded through gson(), read.gson(), write.gson(), as.list(), validate_gson() and print(). It is free text on purpose: validate_gson() asks only for one value or NULL, because an enforced enum would reject every producer that names its domain differently. Files written before the field existed read it back as NULL, and a file that carries it still opens in the released 0.2.1, which ignores the unknown key (verified by reading a gsidtype file with the CRAN build). schema_version is not bumped for it -- gson() still writes 1.0 and a producer that wants to declare 1.1 says so -- but validate_gson() now reports a schema_version it does not recognise instead of staying silent, and never rewrites the value (2026-10-08, Thu)
  • urlpattern can now be consumed: gson_url() returns the URLs of the gene sets, one per ID and defaulting to every names(x) of the object, and browseGS() opens them in a browser. Both were reachable before this release only from inside the package -- browseGS() was never exported, and its sub() call passed the pattern as the string to search, so a vector of gene set IDs collapsed to a single URL -- and browseGS() on an object without a urlpattern computed sub(NULL, ...) into character(0), which browseURL() silently opened nowhere. It is now an error, and gson_url() warns and returns NA instead. The URL comes only from what the object declares: gson ships no table of other databases' websites, so a producer that wants its gene sets browsable declares a urlpattern (read.gmt.wp() does, and ReactomePA::gson_Reactome() currently passes urlpattern = NULL). set_gson(), referenced nowhere in the family, is gone (2026-10-08, Thu)
  • GSON objects can be subset with [: x[i] returns the gene sets selected by i as a GSON. Before, taking a subset meant filtering the three mapping tables by hand -- gson(x@gsid2gene[x@gsid2gene$gsid %in% ids, ]) -- and keeping gsid2name and gene2name in step with gsid2gene oneself, which is easy to get wrong in the direction validate_gson() reports: a gene2name row for a gene that is no longer a member of any gene set. The method prunes the three tables together, filtering gene2name by the genes that survive, and carries every metadata slot (species, gsname, version, accessed_date, keytype, gsidtype, urlpattern, info, schema_version) over to the result. Gene set IDs, positions and logical vectors all select, x[] returns x, and a gene set ID the object does not hold or an index out of bounds is an error that names what is missing. x[, j] is an error too, since a GSON has no second dimension. x[[i]] is unchanged and still returns the genes of a single gene set (2026-10-08, Thu)
  • gson_union() merges several GSON objects, or one GSONList, into a single collection -- the multi-source case (GO + KEGG + REAC as one membership table) that callers used to assemble from rbind() and unique() themselves -- and a GSONList now survives subsetting, since x[1] used to come back as a plain list and lost print.GSONList. Two objects that name the same source (gsname, and gsidtype too once every object declares one) are the same collection: a gene set both of them carry is joined into one set holding every gene either gives it, so two files of one download merge rather than collide. A gene set ID that two *different* sources both use is refused, because the merged table would say that one ID names two sets of genes and every result read from it would be quietly wrong; .conflict = "prefix" qualifies every ID with its source (KEGG:hsa00010) and "rename" qualifies only the colliding ones, leaving IDs that already begin with their source alone, and the gsid2name rows follow the IDs they describe. Of the metadata, species, keytype and schema_version have to agree -- one membership table cannot mean two organisms, two identifier types or two file schemas -- while gsname, gsidtype, version, accessed_date and info are joined with " + " when the sources name themselves differently. urlpattern is kept only when every object declares the same one and no ID moved, because a pattern that resolves part of the collection to the wrong page is worse than no pattern (2026-10-08, Thu)
  • read.gson() says which file is wrong and what about it, instead of passing on whatever jsonlite or utils::stack() happened to notice. A .gson file is written by other programs as often as by this one, and a file that did not follow the format used to fail with a message about R internals rather than about the file: at least one vector element is required when gsid2gene was absent, invalid 'times' value when it held a JSON array of arrays, arguments imply differing number of rows: 1, 0 when it held a string, $ operator is invalid for atomic vectors when the whole file was an array, gsid2name should have at least 2 columns when gsid2name held a string instead of the two arrays gsid and name, and lexical error: invalid char in json text -- quoting the *path* of a file that does not exist -- from jsonlite. Two malformed files read without any error at all: {"gsid2gene": {"": ["101"]}} gave a gene set with an empty ID, and {"gsid2gene": {"GS1": {"a": ["101"]}}} gave GS1 -> 101 with the inner key silently dropped (verified against the released 0.2.1). Each case is now an error naming the file, the member and the shape found -- the gson file <path> holds 'gsid2gene' as a matrix, but the memberships must be an object keyed by gene set ID, e.g. {"GS1": ["101", "102"]} -- a file that will not parse at all reports the gson file <path> could not be read: with the parse error beneath it, and a local path that does not exist is caught before jsonlite is asked (a URL is not, so reading from the web still works). The shapes recognised are the ones jsonlite::fromJSON() actually produces, which simplifies an object of two equal-length arrays to a data.frame and an array of equal-length arrays to a matrix. An empty "gsid2gene": {} is no longer an error either: it is a collection of no gene sets, which is what write.gson() of an empty GSON writes, and the two now round-trip to an identical object. Well-formed files, from this package or from another, read as before (2026-10-08, Thu)
  • validate_gson() reports what the identifier fields claim without carrying: a keytype or gsidtype left at a placeholder -- UNKNOWN, NA, null, none, -, the empty string -- now reads keytype 'UNKNOWN' names no identifier type; leave it NULL when the type is not known, and a gsidtype the object's own gene set IDs contradict reads gsidtype 'KEGG' is not the prefix of the gene set IDs, which begin GO -- as in 'GO:0008150'. There is deliberately no dictionary of accepted values, which is what the same report would need to be complete: MicrobiomeProfiler writes kegg_orthology, kegg_compound, kegg_enzyme, eggNOG_OG, taxid, cog, metabolite_id and hmdb_id as keytype, none of them a keytypes() value of any Bioconductor annotation package, so an enumerated list held by gson would reject the collections the family itself produces and could only be kept current by hand. What gson can verify is an object against itself, so only a prefix the IDs actually carry is compared: identifiers with no prefix (WP5119, hsa00010, the numeric GO IDs some producers write) give nothing to check and are left alone, a gsidtype that gson_union() joined ("GO + KEGG") is read as the several domains it is, and IDs qualified with the source's own gsname -- what .conflict = "prefix" writes -- count as agreement, as does one domain out of several, since a partly right claim is a merged collection rather than a wrong one. Nothing is rewritten, following the unknown schema_version: keytype = "UNKNOWN" is the value enrichit::ora_gson() and gsea_gson() give an enrichResult when a GSON declares none, so it is a value in circulation, and silently turning it into something else would change what a consumer asks an annotation package. validate_gson() throws on a report only when called with the default error = TRUE, and nothing outside gson calls it (verified by searching the family); the collections this package ships stay valid, read.gmt.wp()'s bundled WikiPathways object with gsidtype = "WP" and IDs like WP5119 among them (2026-10-08, Thu)
  • write.gson() writes the gene sets in the order the collection holds them, so a .gson file reads back as the object it was written from. split() sorted the gene set IDs, and a JSON object keeps the order it is written in, so every collection whose own order is not the alphabetical one came back rearranged: the bundled WikiPathways object, whose names() begin WP5119, WP2840, WP4685, read back beginning WP100, WP106, WP107, and identical() of the two was FALSE although all 724 gene sets and all 30629 memberships matched. The order is not decoration -- names(x), print() and x[1] all follow it, so a ranked collection loses what its rank means -- and keeping it costs nothing, since jsonlite::toJSON() writes the members of an object in the order the list holds them (2026-10-08, Thu)
  • An audit of this round's own changes found three gaps at the boundaries it had just added, now closed. read.gson() refused a file holding "GS2": [] with the misleading "not a flat list of identifiers" -- jsonlite reads an empty array as an empty list, so an empty gene set fell into the wrong check -- and now says holds gene set 'GS2' with an empty gene list; a GSON cannot hold a set of no genes, and write.gson() omits such sets with a warning, since dropping the set in silence would look like the file never mentioned it. A hand-written "GS1": ["g1", null] read without complaint into a gene genuinely called NA -- the same disease the write side skips such rows for -- and the read side now skips them on the same terms, warning how many memberships were omitted; a set whose every gene is unusable leaves a collection without it. And validate_gson() silently took a keytype or gsidtype left at NA for absent: an NA slot is not NULL, and it is now reported with the values that name nothing. Files without these defects read exactly as before (2026-10-08, Thu)
Show all changes in 0.2.2Hide the rest of the changes in 0.2.2
  • Description describes what a collection is used for rather than what the object holds: a GSON can be built from data frames, read from and written to the 'gson' JSON and 'GMT' formats, subset by gene set, merged across sources, validated, and resolved to the web addresses of the databases it comes from, which is the point of the format -- a collection gathered by one package is analysed by another. URL and BugReports were missing, so the manual pages and the CRAN page had no link out; they now follow the family convention and point at the book and at YuLab-SMU/gson. Three dependencies that no code reached are gone: rlang was imported for a @importFrom rlang .data tag left over from the tidyr::separate() call 0.2.1 replaced with strsplit(), utils::packageVersion() for the commented-out info line of write.gson(), and digest and fs were listed under Suggests with no reference anywhere in the package or its tests. Of the three, only rlang was under Imports and so was actually loaded -- an importFrom directive pulls the namespace in when gson is loaded -- while digest and fs sat under Suggests and cost nothing but a line of metadata. gson now starts no package its code does not call. R CMD check is unchanged and a GSON built and written before the trim reads identically after it (2026-10-08, Thu)
  • README.Rmd is the source of the readme, and README.md is what it renders, following the convention of the family: the badges, the opening paragraph and the output of every example come out of the package rather than out of memory, so the readme cannot quietly fall behind the code it describes. The readme: target of the Makefile already pointed at this file, which did not exist. It walks through building a collection from two data frames, the .gson round trip

The NEWS section is longer than shown here.

From NEWS.md in the release

Install

Health

CRAN checks
13OK
Slowest check: 1.3 min · r-oldrel-windows-x86_64
Status changes
  • OK13 OK2026-08-05
  • NOTE12 OK, 1 NOTE2026-08-01
  • OK14 OK2026-03-10
Advisories

none known

Documentation

In release 0.2.2
READMEYes · 1,363 wordsVignettesNoNEWSYes · 100% structured · mentions 0.2.2Citation fileNoWebsiteYes
Help pages
12 (1 internal)includes a package overview page
Examples that run
100%5 run in a plain check
Exported functions with examples
71%
Documented parameters
89%
Return-value docs
100%
Help pages citing references
0%

Downloads

421.1K
CRAN downloads in the past year
Rank #495 · ~1.2K/day · ~35.1K/mo
Daily download trend is not available in this view yet.
44.2K30 days
150.4K90 days
421.1K1 year
Compare downloads with other packages →
Also on8K r2u2 autocran87.2K conda_forge176 c2d4u

Repository

3Stars
4Forks
0Open issues
0Open PRs
0Releases
64Commits
2Commit identities
64 commits · Last activity 2026-10-09
Responsiveness
How these are sampled
PRs merged (all time)
57%
Median days to close, 50 most recently updated closed issues
70
Median days to close, 50 most recently updated closed PRs
1
PracticesBeta

3 development-tooling and community-health practices detected across 3 families in the upstream repository

Checks run against github.com/yulab-smu/gson on 2026-10-18.

Docs source (1)
README.Rmd
Reproducibility and dev environment (1)
Makefile
CRAN release process (1)
CRAN-SUBMISSION
How this is detected·Detection ruleset v3 (2026-09-26)

Dependencies

Declared dependencies
3 external dependencies (excludes base and recommended)

Installing gson adds 7 packages (6 with compiled code, 4.0 MB of source tarballs). Heaviest: fs 1.4 MB, jsonlite 1.0 MB, rlang 766 KB.

Depends (0)
none
Imports (5)
jsonlitemethodsstatsutilsyulab.utils
LinkingTo (0)
none
Suggests (1)
Enhances (0)
none
Reverse dependencies
1direct
0indirect
Imports 1
Suggested by 1
Depends, Imports or LinkingTo, most downloaded first
Suggests, most downloaded first

People & History

People (1)
Author, Maintainer since 0.0.4 (2022), Copyright holder
Releases (9)

Pick two releases to compare their code metrics.

  • 0.2.2Latest
    record
    2026-10-09 · current release · diff ↗ ·
    added 3 exports
    browseGS, gson_union, gson_url
  • 0.2.1
    record
    2026-08-04 · diff ↗
  • R
    R 4.6.0 released · 2026-04-24
  • R
    R 4.5.0 released · 2025-04-11
  • R
    R 4.4.0 released · 2024-04-24
  • R
    R 4.3.0 released · 2023-04-21
  • 0.2.0
    record
    2023-03-07 · diff ↗ ·
    added 2 exports
    validate_gson, write.gmt
  • 0.1.0
    record
    2023-03-07 · diff ↗
  • 0.0.9
    record
    2022-09-06 · diff ↗ ·
    added 1 export
    gsonList
  • 0.0.8
    record
    2022-08-20 · diff ↗
  • 0.0.7
    record
    2022-08-09 · diff ↗
  • 0.0.6
    record
    2022-06-07 · diff ↗
  • 0.0.4
    record
    2022-04-28
  • R
    R 4.2.0 released · 2022-04-22

Package metadata

First published
2022-04-28
Total releases
9 / 4 yrs
License
Artistic-2.0 OSI
Download size
130 KB

Cite

Cite this package

Run in R for the authors' preferred citation:

citation("gson")
Yu, G. (2026). gson: Base Class and Methods for 'gson' Format (Version 0.2.2) [Computer software]. https://doi.org/10.32614/CRAN.package.gson

This package has no citation file, so citation() returns this entry built from DESCRIPTION.

Cite the R Observatory

For a number measured here: a download total, a coverage figure, an archival date.

APA

Balamuta, J. J. (2026). R Observatory: Metrics for gson version 0.2.2 [Data set]. HJJB, LLC. Data release v2026-10-22. https://doi.org/10.5281/zenodo.21843040

From data release v2026-10-22, which the citation names so these numbers can be found later. More on citing and the projects behind them.

Report a problem with this page →

Privacy choices

These apply to this browser and are stored on this device only. Nothing about your choice is sent to us.

Read the privacy policy