Card Loading and Validation - UQcsse3200/2026-studio-3 GitHub Wiki

Overview

CardConfigLoader loads card definitions from JSON, checks that the file and its contents are valid, and converts each definition into a CardConfig object.

The default configuration is loaded from:

source/core/assets/configs/cards.json

In code, this is referenced as:

configs/cards.json

This is because LibGDX resolves internal file paths relative to the core/assets directory.

Loading Workflow

The card-loading process is:

cards.json
→ file and JSON structure checks
→ CardConfig deserialisation
→ CardValidator validation
→ duplicate ID detection
→ immutable list of CardConfig objects

The default configuration can be loaded with:

List<CardConfig> cards = CardConfigLoader.loadCards();

A different internal asset file can also be provided:

List<CardConfig> cards =
    CardConfigLoader.loadCards("configs/custom_cards.json");

Validated cards can then be registered in CardLibrary:

CardLibrary library =
    new CardLibrary(CardConfigLoader.loadCards());

Other systems should retrieve card definitions through CardLibrary or CardService instead of parsing cards.json directly.

File Structure Validation

Before creating any cards, the loader checks that:

  • The filename is not null or blank.
  • The requested file exists.
  • The file contains valid JSON.
  • The JSON root is an object.
  • The root contains a cards array.
  • The cards array contains at least one entry.
  • Every card entry is a JSON object.

Every card must explicitly contain these fields:

id
name
description
cost
type
rarity
target
effects
texturePath

Card Validation

After deserialisation, each card is passed to CardValidator for value-level validation. This checks properties such as IDs, costs, targets, effects, effect values and durations.

The loader also checks for duplicate card IDs. Duplicate detection is case-sensitive and prevents one card definition from silently replacing another.

If multiple cards contain errors, the loader collects the errors and reports them together. Error messages include the card index and its ID when available, making invalid entries easier to locate.

The loader never returns a partially valid collection. If any error is found, loading fails with CardLoadingException. If all cards are valid, the result is returned using List.copyOf, so callers cannot modify the loaded collection.

Error Handling

CardLoadingException is thrown when the configuration cannot be loaded or validated. Examples include:

  • Missing or invalid file paths
  • Malformed JSON
  • Invalid root structures
  • Missing or empty cards arrays
  • Null or non-object card entries
  • Missing required fields
  • Unsupported enum values
  • Invalid card or effect values
  • Duplicate card IDs

Malformed JSON errors preserve the original exception as the cause. This provides useful diagnostic information without exposing partially loaded card data.

Example:

try {
  CardLibrary library =
      new CardLibrary(CardConfigLoader.loadCards());
} catch (CardLoadingException exception) {
  // Report the configuration problem and stop card initialisation.
}

Design Decisions

Separate loading and semantic validation

CardConfigLoader is responsible for reading the file, checking its structure and converting JSON into Java objects. CardValidator is responsible for checking whether the resulting card values are valid.

This separation keeps the loader focused on file handling while allowing the same validation rules to be reused by CardLibrary.

Aggregated error reporting

The loader reports all detected card errors together instead of stopping at the first invalid entry. This makes configuration problems faster to identify and fix.

Immutable results

Successfully loaded cards are returned as an immutable list. This prevents callers from accidentally adding or removing entries after validation.

Testing

CardConfigLoaderTest contains 13 tests covering:

  • Valid configuration loading
  • Default file loading
  • Registration with CardLibrary
  • Immutable results
  • Null and blank filenames
  • Missing files
  • Malformed JSON
  • Invalid root structures
  • Missing and empty cards arrays
  • Null card entries
  • Missing required fields
  • Invalid card values and unsupported types
  • Duplicate card IDs
  • Aggregated validation errors

The tests can be run from the source directory:

.\gradlew.bat core:test --tests "com.csse3200.game.cards.CardConfigLoaderTest"

The full card and project tests can be run with:

.\gradlew.bat core:test
.\gradlew.bat spotlessCheck

All loader tests, existing project tests and formatting checks passed after integration into Feature6.

Known Limitations

  • texturePath is checked only for a non-blank value. The loader does not confirm that the referenced artwork exists on disk.
  • The current production card artwork paths are placeholders and their image files have not yet been added.
  • description is required by CardConfigLoader, but it is not currently required by CardValidator.
  • Card IDs are case-sensitive.
  • Any invalid card prevents the entire configuration from loading; partial loading is intentionally unsupported.

Related Documentation

⚠️ **GitHub.com Fallback** ⚠️