Skip to content

Add better support for multiple top-level values#2783

Open
Marcono1234 wants to merge 5 commits intogoogle:mainfrom
Marcono1234:marcono1234/multi-top-level-value
Open

Add better support for multiple top-level values#2783
Marcono1234 wants to merge 5 commits intogoogle:mainfrom
Marcono1234:marcono1234/multi-top-level-value

Conversation

@Marcono1234
Copy link
Contributor

@Marcono1234 Marcono1234 commented Dec 26, 2024

Purpose

Add better support for reading and writing multiple top-level values

Description

Currently reading and writing multiple top-level JSON values is coupled with lenient mode. This might be undesired for users who normally want to use strict mode.
Having multiple top-level values is a common use case when streaming JSON values, see for example JSON Lines. And another problem is that JsonWriter currently concatenates multiple JSON values without any separating whitespace, and without any way to configure it.

Other JSON libraries seem to have dedicated classes or configuration for multiple top-level value support, e.g. Jackson's MappingIterator and SequenceWriter and kotlinx-serialization's DecodeSequenceMode.WHITESPACE_SEPARATED.
However, because Gson's JsonReader and JsonWriter already had (limited) functionality for multiple top-level values, I added new API to those classes instead of adding completely new classes.

Exposing this also through Gson / GsonBuilder might not be needed since the methods of the Gson class are mainly for reading and writing a single value.

Checklist

  • New code follows the Google Java Style Guide
    This is automatically checked by mvn verify, but can also be checked on its own using mvn spotless:check.
    Style violations can be fixed using mvn spotless:apply; this can be done in a separate commit to verify that it did not cause undesired changes.
  • If necessary, new public API validates arguments, for example rejects null
  • New public API has Javadoc
    • Javadoc uses @since $next-version$
      ($next-version$ is a special placeholder which is automatically replaced during release)
  • If necessary, new unit tests have been added
    • Assertions in unit tests use Truth, see existing tests
    • No JUnit 3 features are used (such as extending class TestCase)
    • If this pull request fixes a bug, a new test was added for a situation which failed previously and is now fixed
  • mvn clean verify javadoc:jar passes without errors

Comment on lines +434 to +446
public final void setMultiTopLevelValuesAllowed(boolean enabled) {
this.multiTopLevelValuesEnabled = enabled;
}

/**
* Returns whether multiple top-level values are allowed.
*
* @see #setMultiTopLevelValuesAllowed(boolean)
* @since $next-version$
*/
public final boolean isMultiTopLevelValuesAllowed() {
return multiTopLevelValuesEnabled;
}
Copy link
Contributor Author

@Marcono1234 Marcono1234 Dec 26, 2024

Choose a reason for hiding this comment

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

I am not completely happy about these method names setMultiTopLevelValuesAllowed and isMultiTopLevelValuesAllowed yet. Any feedback and suggestions are welcome.

Copy link
Member

Choose a reason for hiding this comment

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

What about setAllowingMultipleValues and isAllowingMultipleValues? "Multiple values" isn't quite as precise as "multi top-level values", but the latter is kind of verbose. I'm proposing "allowing X" rather than "X allowed" to avoid the grammatical issue with "is top-level values allowed".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, have renamed the methods. I have left the corresponding test methods unchanged (enabled/disabled) to make it more obvious that they are about explicitly enabling / disabling this.

@Marcono1234
Copy link
Contributor Author

An alternative would be to always enable support for multiple top-level values, regardless of strictness, and then only have JsonWriter#setTopLevelSeparator(String) to allow customizing the separator when writing.

Though since there are multiple formats / standards for encoding multiple top-level values, maybe this is not desired? And could cause confusion when users accidentally write or read multiple top-level values? (though a bit unlikely?)

Copy link
Member

@eamonnmcmanus eamonnmcmanus left a comment

Choose a reason for hiding this comment

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

If you are on for reviving this, I have run across some use cases for it and would be interested in following through, ideally before the next release.

Comment on lines +434 to +446
public final void setMultiTopLevelValuesAllowed(boolean enabled) {
this.multiTopLevelValuesEnabled = enabled;
}

/**
* Returns whether multiple top-level values are allowed.
*
* @see #setMultiTopLevelValuesAllowed(boolean)
* @since $next-version$
*/
public final boolean isMultiTopLevelValuesAllowed() {
return multiTopLevelValuesEnabled;
}
Copy link
Member

Choose a reason for hiding this comment

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

What about setAllowingMultipleValues and isAllowingMultipleValues? "Multiple values" isn't quite as precise as "multi top-level values", but the latter is kind of verbose. I'm proposing "allowing X" rather than "X allowed" to avoid the grammatical issue with "is top-level values allowed".

* @see #getTopLevelSeparator()
* @since $next-version$
*/
public final void setTopLevelSeparator(String separator) {
Copy link
Contributor Author

@Marcono1234 Marcono1234 Feb 20, 2026

Choose a reason for hiding this comment

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

Not sure if we should also support an boolean addTrailing parameter, so that the JsonWriter emits the separator also after the last element.

It seems JSON Lines recommends adding a trailing line break, though does not require it. Not sure about other multi-value JSON standards.

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.

JsonReader with strictness set to LENIENT,

2 participants