Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Proposal for improving tapestry-json with Java 8 features and more

tapestry-json Improvements

Date: 2020-07-26
Author: Ben Weidig


Add modern Java 8 features to tapestry-json to make it more versatile. Improve existing functionality without breaking changes.


With Tapestry development picking up speed and supporting newer Java version, its dependencies should also support some of the newly available features:

  • Stream-support
  • Additional instance creators
  • Approximate to the conceptional interfaces (Collection/Map)
  • Generic methods
  • Better/more informative exceptions

The general idea is making JSONArray more like java.util.Collection, and JSONObject more like java.util.Map, without implementing the interfaces explicitly. If we would implement them directly, it would method duplication (size() vs. length(), add() vs put(...)).


Tapestry's use of JSON types is deeply ingrained into its services. By using its own types, we can improve upon them to adapt to any new features. The framework and Java itself evolved, and they should be too.

Java 8 was bringing a lot of new features, like lambdas, Streams, and Optionals, thereby changing the way how we can deal with collection types in a significant way.

It's time to adapt tapestry-json to the new features available to us.

Risks and Assumptions

Only minimal risk is assumed.

Existing functionality shouldn't be changed, for backward-compatibility. Any new feature has to be able to stand on its own.

The only proposed change will be the exact exception types and messages. Changing the type should not pose a problem, they will still be descendant of RuntimeException. And relying on the actual exception message is bad practice, and shouldn't be part of the guaranteed API contract.


Instead of extending existing types we could always use utility classes to wrap the functionality.

Details of Proposed Changes

Most of the proposed changes are based on utility classes used in our projects. But some are just of theoretical nature, and might not be as easy as implementable as thought.


  • Stream<Object> stream()
  • Stream<T> stream(Class<T> clazz)
  • Stream<Object> parallelStream()
  • Stream<T> parallelStream(Class<T> clazz)
  • List<T> toList(Class<T> clazz)
  • static JSONArray from(Iterable<?> iterable, boolean preserveNull)
  • JSONArray(String jsonStr, boolean emptyIfInvalid)
  • boolean putUnique(Object value)
  • boolean isEmpty()
  • boolean contains(Object obj)
  • boolean removeIf(Predicate<Object> filter)
  • boolean removeAll(Iterable<Object> iterable)
  • void clear()


  • Map<String, T> toMap(Class<T> valueClazz)
  • Optional<Type> tryGetType(String key) for all types
  • Type getType(String key, Type fallbackValue) for all types
  • static JSONObject from(Map<String, ?> map)
  • void clear()
  • void clear()
  • Object putIfAbsent(String key, Object value)
  • Object computeIfAbsent(String key, Function<String, Object> mapFn)
  • Object computeIfPresent(String key, Function<String, Object> remapFn)
  • void merge(JSONObject other)


  • Use IndexOutOfBoundsException correctly
  • org.apache.tapestry5.json.JSON should throw more fine-grained exceptions:
    • Add JSONTypeUnsupportedException
    • Add JSONTypeMismatchException
    • Add JSONValueNotFoundException


  • Add Collectors to improve Stream use


All added functionality should be unit tested to ensure no existing code will be broken by it.


This comment has been minimized.

Copy link

@MarineBerth MarineBerth commented Oct 7, 2020

Hi Ben, just a friendly follow-up to see how you are progressing with this proposed improvement? All the best, Chris.


This comment has been minimized.

Copy link
Owner Author

@benweidig benweidig commented Oct 7, 2020

Hi Chris,

Thiago already merged the improvements into master (apache/tapestry-5@2dab8e0) and marked the ticket as "Fixed Version/s: 5.6.2"

Although the actual changes are a little different, JSONArray and JSONCollection now implement Collection and Map directly, instead of just mimicking the behaviour.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.