Skip to content

Add JSON concept exercise (marshal and unmarshal) - #88

Merged
zhravan merged 5 commits into
zhravan:mainfrom
sidharth-chauhan:json-exercise
Oct 1, 2025
Merged

Add JSON concept exercise (marshal and unmarshal)#88
zhravan merged 5 commits into
zhravan:mainfrom
sidharth-chauhan:json-exercise

Conversation

@sidharth-chauhan

@sidharth-chauhan sidharth-chauhan commented Sep 29, 2025

Copy link
Copy Markdown
Contributor

Summary

Added a new concept exercise for JSON under internal/exercises/templates/36_json/.

Details

  • Introduced json.go as a template file for learning JSON encoding and decoding.
  • Added json_test.go with tests for MarshalPerson and UnmarshalPerson.
  • Updated catalog.yaml to include the new JSON concept.
  • The exercise teaches basic usage of the encoding/json package in Go.

Notes

All tests and formatting follow existing exercise conventions.

Closes #81

Summary by CodeRabbit

  • New Features
    • Added a JSON concept exercise teaching JSON encoding/decoding and error handling with Go’s standard library; includes a hands-on task to serialize/deserialize a simple contact object and learner-facing hints.
  • Tests
    • Added unit tests validating serialization and deserialization behavior for the exercise.
  • Documentation
    • Updated the exercise catalog with the new JSON entry and guidance.

@coderabbitai

coderabbitai Bot commented Sep 29, 2025

Copy link
Copy Markdown

Walkthrough

Adds a new JSON exercise (slug 36_json) to the exercises catalog and introduces template and test files: a Person type plus stubbed MarshalPerson and UnmarshalPerson functions and tests verifying JSON marshal/unmarshal behavior.

Changes

Cohort / File(s) Summary of Changes
Catalog entry: JSON (slug 36_json)
internal/exercises/catalog.yaml
Added new project entry 36_json (title "JSON", test_regex: ".*") with hints referencing encoding/json, implementing MarshalPerson and UnmarshalPerson, and instructing to handle and return errors.
Exercise template: JSON implementation
internal/exercises/templates/36_json/json.go
Added Person type with json:"name" and json:"email" tags and exported functions MarshalPerson(p Person) (string, error) and UnmarshalPerson(jsonStr string) (Person, error); implementations are currently placeholders returning zero values and nil error, with comments guiding correct implementation.
Tests: JSON exercise
internal/exercises/templates/36_json/json_test.go
Added tests TestMarshalPerson and TestUnmarshalPerson that assert exact JSON output from MarshalPerson and correct field parsing and error handling from UnmarshalPerson.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer/Test
  participant EX as json package (exercise)
  participant EJ as encoding/json

  rect rgb(235,245,255)
    note over Dev,EX: Marshal flow (new)
    Dev->>EX: MarshalPerson(p)
    EX->>EJ: json.Marshal(p)
    EJ-->>EX: []byte / error
    EX-->>Dev: string / error
  end

  rect rgb(240,255,240)
    note over Dev,EX: Unmarshal flow (new)
    Dev->>EX: UnmarshalPerson(jsonStr)
    EX->>EJ: json.Unmarshal([]byte(jsonStr), &Person)
    EJ-->>EX: error or Person
    EX-->>Dev: Person / error
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A rabbit nudges keys with a gleeful hop,
Wrapping names and emails in JSON top to top.
Marshal the carrots, unmarshal the hay,
Return the errors, then bounce away.
Tests blink green — now off I hop! 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly summarizes the creation of a new JSON concept exercise with marshal and unmarshal functionality, matching the main change of adding this exercise to the repository.
Linked Issues Check ✅ Passed The pull request includes the required template file (json.go) under internal/exercises/templates/36_json, the corresponding tests (json_test.go), an updated catalog.yaml entry for slug “36_json” with hints on using encoding/json and handling errors, satisfying all four acceptance criteria from issue #81.
Out of Scope Changes Check ✅ Passed All changes are confined to adding the JSON exercise: the new template and test files under internal/exercises/templates/36_json and updating catalog.yaml, with no unrelated modifications outside these areas.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d8016a and 2f018a9.

📒 Files selected for processing (1)
  • internal/exercises/catalog.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/exercises/catalog.yaml

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
internal/exercises/templates/36_json/json_test.go (3)

13-15: Avoid brittle string-equality for JSON; compare semantically instead.

String order/whitespace aren’t guaranteed across encoders. Prefer unmarshalling and comparing maps/structs.

Option A (compare as maps):

-import "testing"
+import (
+	"encoding/json"
+	"reflect"
+	"testing"
+)
@@
-expected := `{"name":"golearn","email":"golearn@example.com"}`
-if jsonStr != expected {
-	t.Errorf("Expected %s, got %s", expected, jsonStr)
-}
+expected := `{"name":"golearn","email":"golearn@example.com"}`
+var got, want map[string]any
+if err := json.Unmarshal([]byte(jsonStr), &got); err != nil {
+	t.Fatalf("MarshalPerson returned invalid JSON: %v", err)
+}
+if err := json.Unmarshal([]byte(expected), &want); err != nil {
+	t.Fatalf("test setup invalid JSON: %v", err)
+}
+if !reflect.DeepEqual(got, want) {
+	t.Errorf("JSON mismatch.\nwant: %v\ngot:  %v", want, got)
+}

Option B (keep string check but normalize): marshal both through json.Encoder with SetIndent/SetEscapeHTML and compare.


15-15: Quote values in failure messages for clarity.

Using %q makes diffs clearer when strings contain spaces/special chars.

- t.Errorf("Expected %s, got %s", expected, jsonStr)
+ t.Errorf("Expected %q, got %q", expected, jsonStr)
@@
- t.Errorf("Expected name 'golearn', got %s", p.Name)
+ t.Errorf("Expected name %q, got %q", "golearn", p.Name)
@@
- t.Errorf("Expected email 'golearn@example.com', got %s", p.Email)
+ t.Errorf("Expected email %q, got %q", "golearn@example.com", p.Email)

Also applies to: 27-31


19-33: Add a negative test to enforce error handling on invalid JSON.

Hints mention proper error handling; a failing case will guard regressions.

 func TestUnmarshalPerson(t *testing.T) {
@@
 }
+
+func TestUnmarshalPerson_InvalidJSON(t *testing.T) {
+	// missing closing brace
+	jsonStr := `{"name":"golearn","email":"golearn@example.com"`
+	_, err := UnmarshalPerson(jsonStr)
+	if err == nil {
+		t.Fatalf("Expected error for invalid JSON, got nil")
+	}
+}
internal/exercises/templates/36_json/json.go (2)

1-1: Package name json can confuse learners alongside importing encoding/json.

It’s valid, but referencing json.Marshal will point to the stdlib import while types here are unqualified. Consider adding a brief note in the task comment to clarify, or alias the import as stdjson in examples/hints for readability.


16-19: Stubs return zero values with nil error; confirm CI excludes failing exercises.

As written, tests will fail until learners implement these. Ensure your CI doesn’t run exercise tests (or marks them with build tags/skip) to avoid breaking main.

If you prefer to make intent explicit while still compiling, consider returning a sentinel error:

+import "errors"
@@
-func MarshalPerson(p Person) (string, error) {
-	return "", nil
-}
+func MarshalPerson(p Person) (string, error) {
+	return "", errors.New("TODO: implement MarshalPerson")
+}
@@
-func UnmarshalPerson(jsonStr string) (Person, error) {
-	return Person{}, nil
-}
+func UnmarshalPerson(jsonStr string) (Person, error) {
+	return Person{}, errors.New("TODO: implement UnmarshalPerson")
+}

Alternatively, add a build tag (if that’s your convention) to keep exercise files out of CI. I can align this to your existing pattern if you share it.

Also applies to: 21-24

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0e24a7 and b733bdb.

📒 Files selected for processing (3)
  • internal/exercises/catalog.yaml (1 hunks)
  • internal/exercises/templates/36_json/json.go (1 hunks)
  • internal/exercises/templates/36_json/json_test.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
internal/exercises/templates/36_json/json_test.go (1)
internal/exercises/templates/36_json/json.go (3)
  • Person (11-14)
  • MarshalPerson (17-19)
  • UnmarshalPerson (22-24)

Comment thread internal/exercises/catalog.yaml Outdated
@zhravan zhravan added patch Bug fixes and small improvements hacktoberfest Hacktoberfest participation hacktoberfest-accepted hacktoberfest2025 labels Oct 1, 2025
@zhravan
zhravan merged commit 5c8c284 into zhravan:main Oct 1, 2025
@zhravan

zhravan commented Oct 1, 2025

Copy link
Copy Markdown
Owner

PR LGTM, thank you so much considering to contribute to the project

This was referenced Oct 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hacktoberfest Hacktoberfest participation hacktoberfest2025 hacktoberfest-accepted patch Bug fixes and small improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Concept] JSON - add exercise templates

2 participants