Java JSON (Jackson)

Java JSON (Jackson)


JSON + Jackson Foundations

Q1: What is JSON?

JSON is a lightweight text format for structured data exchange. It is language-agnostic and commonly used in REST APIs, messaging, and config. Jackson maps JSON to Java objects and back. {"id":1,"name":"Ana"}

Q2: What is Jackson in Java?

Jackson is a popular library for JSON serialization/deserialization. It provides flexible data binding, tree model, and streaming APIs used in most Java backend systems. Spring Boot uses Jackson by default for JSON bodies.

Q3: Serialization vs deserialization?

Serialization = Java object -> JSON, deserialization = JSON -> Java object. Correct schema mapping is critical for API compatibility and data integrity. UserDto to JSON response and back from request body.

Q4: What is ObjectMapper?

Core Jackson class for reading/writing JSON. ObjectMapper is thread-safe after configuration and should usually be reused as singleton bean.

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);

Q5: Why avoid creating ObjectMapper repeatedly?

Reusing is faster and consistent. Recreating mapper per request increases overhead and risks inconsistent config across code paths. configure one @Bean ObjectMapper in Spring.

Q6: What are Jackson core models?

Data binding, tree model, and streaming model. Choose model by use case: POJO mapping for common cases, JsonNode for dynamic JSON, streaming for very large payloads. readValue (POJO), readTree (JsonNode), JsonParser (streaming).

Q7: Why is DTO recommended for JSON contracts?

DTO isolates API schema from domain/entity internals. Prevents accidental field leakage, lazy-loading issues, and contract breakage during refactors. expose UserResponse instead of JPA UserEntity.

Q8: Can Jackson handle Java records?

Yes. Records are great immutable DTOs for clear API contracts and reduced boilerplate.

public record UserResponse(Long id, String name) {}

Q9: What does FAILONUNKNOWNPROPERTIES do?

Controls behavior for unknown JSON fields during deserialization. Disabling can improve forward compatibility; enabling can enforce strict schema. tolerate extra fields from newer client version.

Q10: JSON null vs missing field difference?

null is explicit value; missing means absent key. This difference matters for PATCH semantics and partial updates. {"name":null} vs {}


ObjectMapper Basic Operations

Q11: How to convert object to JSON string?

writeValueAsString. Most common serialization method in services and tests.

String json = mapper.writeValueAsString(dto);

Q12: How to parse JSON string into object?

readValue(json, Class). Ensure class fields/types align with payload schema.

UserDto dto = mapper.readValue(json, UserDto.class);

Q13: How to read JSON from file?

readValue(File, Class). Useful for config/bootstrap data and integration tests. loading seed JSON test data.

Q14: How to write JSON to file?

writeValue(File, Object). Good for exports/log snapshots; ensure encoding and file permissions. persist report data as JSON file.

Q15: How to pretty print JSON?

Use pretty printer. Better readability for logs/debug, but avoid in high-volume production responses unless needed.

String pretty = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(dto);

Q16: convertValue use case?

Convert one object type to another using Jackson mapping. Handy for DTO transformations without manual mapping in some cases. Map<String,Object> -> typed DTO.

Q17: readTree use case?

Parse into JsonNode tree for dynamic structure access. Useful when schema is partially unknown or needs selective extraction. read only payload.meta.traceId.

Q18: treeToValue / valueToTree use case?

Bridge between JsonNode and POJO. Useful in mixed dynamic+typed pipelines. parse root as JsonNode, convert subnode to typed class.

Q19: TypeReference why needed?

Preserve generic type info during deserialization. Java type erasure loses runtime generic details without TypeReference.

List<UserDto> users = mapper.readValue(json, new TypeReference<List<UserDto>>() {});

Q20: Common beginner Jackson mistake?

Ignoring exceptions and schema mismatch. Silent assumptions cause runtime mapping failures in production payloads. field type mismatch age:"abc" for int field.


Core Annotations for Mapping Control

Q21: What does @JsonProperty do?

Maps Java field/property to specific JSON key. Useful for naming mismatches and explicit contract declaration. firstName <-> "firstname".

Q22: What does @JsonIgnore do?

Excludes field from serialization/deserialization. Helps hide internal/sensitive fields from API payloads. ignore internalToken.

Q23: @JsonIgnoreProperties(ignoreUnknown = true) purpose?

Ignore extra JSON fields. Improves compatibility when producers add new non-breaking fields. older service reading newer payload safely.

Q24: What does @JsonInclude do?

Controls inclusion policy (e.g., non-null only). Reduces payload noise and supports clean API responses. Include.NONNULL omits null fields.

Q25: What does @JsonFormat do?

Controls formatting for date/time/number fields. Useful for stable, explicit representation in API contracts. date pattern yyyy-MM-dd.

Q26: @JsonAlias use case?

Accept multiple input names for same field. Helps migration/compatibility with legacy payload variants. accept firstname and firstName.

Q27: @JsonGetter / @JsonSetter use?

Custom getter/setter mapping names/logic. Useful when property methods need explicit JSON binding behavior. computed output field via getter.

Q28: @JsonCreator purpose?

Defines constructor/factory for deserialization. Important for immutable classes/records when custom construction needed. constructor parameter mapping with @JsonProperty.

Q29: @JsonAnySetter / @JsonAnyGetter purpose?

Capture/emit dynamic key-value fields. Useful for extensible metadata sections with unknown keys. additional attributes map.

Q30: Annotation best-practice rule?

Keep annotations minimal and intentional. Too many annotations create hidden complexity; prefer clean DTOs and centralized config where possible. avoid mixing conflicting include/ignore rules.


Date/Time and Java 8+ Types

Q31: Why does LocalDateTime need special support?

Requires Java Time module. Without JavaTimeModule, serialization/deserialization of java.time types may fail or be undesirable format. register JavaTimeModule.

Q32: How to configure ObjectMapper for java.time?

Register JavaTimeModule and configure timestamp behavior. Most APIs prefer ISO-8601 strings, not numeric timestamps.

mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

Q33: Why store/transmit timestamps in UTC?

Avoid timezone ambiguity. UTC simplifies distributed systems and cross-region consistency. use Instant in persistence/audit payloads.

Q34: LocalDate vs Instant in APIs?

LocalDate for date-only; Instant for absolute moment. Choose type matching business semantics to avoid confusion. birthday = LocalDate, eventCreatedAt = Instant.

Q35: @JsonFormat on date fields when useful?

For strict readable date patterns. Useful for compatibility with clients expecting exact format. @JsonFormat(pattern = "yyyy-MM-dd")

Q36: Common date/time bug with Jackson?

Inconsistent timezone assumptions. One service serializes in local zone, another expects UTC => shifted times. 2-hour offset bug in Europe summer time.

Q37: Should API expose LocalDateTime directly?

Usually prefer Instant/OffsetDateTime for timestamps. LocalDateTime lacks timezone/offset context, causing ambiguity across systems. same local time interpreted differently in different regions.

Q38: How to ensure stable time serialization?

Standardize ObjectMapper config globally. One centralized config avoids endpoint-by-endpoint drift. shared Spring Boot Jackson config bean.

Q39: What about Duration/Period serialization?

Supported with proper module/config. Ensure clients agree on representation (ISO-8601 text often best). PT15M duration.

Q40: Date/time best-practice one-liner?

Use explicit types + explicit timezone policy. Ambiguity is the root of most distributed time bugs. UTC Instant in JSON contracts.


Collections, Generics, and Complex Types

Q41: Why generic collection deserialization can fail?

Type erasure loses runtime generic info. Jackson needs TypeReference/JavaType for List<T>, Map<K,V>, etc. new TypeReference<Map<String, Object>>() {}

Q42: How to parse List<UserDto>?

Use TypeReference. Prevents LinkedHashMap fallback and class cast issues.

List<UserDto> list = mapper.readValue(json, new TypeReference<List<UserDto>>() {});

Q43: How to parse Map<String, List<OrderDto>>?

TypeReference with nested generics. Strong typing avoids runtime casting risks. nested TypeReference definition.

Q44: Why does Jackson sometimes deserialize to LinkedHashMap?

Missing target type info. Without explicit type, Jackson chooses generic map structures. readValue(json, List.class) gives List<LinkedHashMap>.

Q45: JsonNode vs Map for dynamic payloads?

JsonNode is richer JSON-aware API. Node API supports path traversal and type-safe checks better than raw map casts. node.path("meta").path("id").asText().

Q46: Handling polymorphic JSON types?

Use type metadata with care. Polymorphic deserialization is powerful but has security implications if misconfigured. sealed hierarchy DTO with controlled subtype mapping.

Q47: What is JavaType in Jackson?

Explicit runtime type descriptor. Useful for advanced generic type construction via TypeFactory. collectionType for List<UserDto>.

Q48: Should API payloads be deeply nested?

Prefer moderate depth. Deep nesting complicates validation, client parsing, and backward compatibility. flatten unnecessary wrapper levels.

Q49: How to parse partial fields only?

Use JsonNode or streaming parser. Avoid full object binding when only subset needed for performance. read only id and status from large payload.

Q50: Generic mapping best practice?

Always provide explicit target type. Strong typing catches issues early and simplifies maintenance. never use raw List.class for typed lists.


Error Handling and Validation

Q51: Common Jackson exceptions?

JsonProcessingException and subclasses. Includes parse errors, invalid format, unknown type, mismatched input. invalid JSON syntax throws parsing exception.

Q52: MismatchedInputException meaning?

JSON shape/type doesn’t match target class. Typical issue when expecting object but receiving array/string. field expects int but receives "abc".

Q53: How to return clean API errors for JSON parse failures?

Global exception handler mapping to 400 Bad Request. Avoid leaking stack traces; provide clear client-facing error and internal logs. @ControllerAdvice handles HttpMessageNotReadableException.

Q54: Validation vs deserialization errors?

Deserialization checks structure/type; validation checks business constraints. Both are needed: JSON may parse but still violate domain rules. age parses as 5 but violates min age 18 rule.

Q55: Why keep error responses consistent?

Better client integration and debugging. Standard schema (code/message/path/timestamp/correlationId) improves operability. same error format for parse and validation failures.

Q56: Should unknown JSON fields always be ignored?

Depends on contract strictness. Ignore for forward compatibility, fail for strict controlled interfaces. public API tolerate extras; internal strict pipeline may reject.

Q57: How to detect invalid enum values?

Jackson throws mapping error unless configured otherwise. You can customize handling for safer defaults or explicit rejection. unknown status string triggers 400.

Q58: Can Jackson coerce types automatically?

Sometimes yes. Coercion can be convenient but risky; strict configs reduce surprises. "1" to int may parse, but strict mode may reject.

Q59: Why log raw bad payload cautiously?

Security/privacy risks. Payload may contain secrets/PII; redact sensitive fields in logs. mask password/token before logging.

Q60: Error-handling best-practice line?

Fail clearly for clients, log safely for operators. Good error design improves both developer experience and incident response. 400 with field-level reason + sanitized server logs.


Custom Serialization/Deserialization

Q61: When to write custom serializer?

When default JSON output is not suitable. Use for domain-specific formatting, compact payloads, or legacy contract compatibility. money object serialized as "12.50 USD".

Q62: When to write custom deserializer?

When input format needs custom parsing logic. Useful for non-standard formats and backward compatibility bridges. parse multiple date patterns into one field.

Q63: How to register custom serializer/deserializer?

Via Module (SimpleModule). Central registration keeps behavior consistent and testable.

SimpleModule m = new SimpleModule();
m.addSerializer(Money.class, new MoneySerializer());
mapper.registerModule(m);

Q64: JsonSerializer role?

Defines how object becomes JSON. You control field shape and output tokens directly. write object with custom field names.

Q65: JsonDeserializer role?

Defines how JSON becomes object. Handle flexible/legacy formats while preserving strong domain model. parse "Y"/"N" into boolean.

Q66: Custom (de)serializers risk?

Added complexity and maintenance burden. Keep logic minimal and well-tested to avoid hidden parsing bugs. serializer/deserializer pair round-trip tests.

Q67: What is @JsonSerialize/@JsonDeserialize?

Per-field/class custom handler binding. Useful when only specific DTO fields need custom behavior. custom BigDecimal formatting on price field.

Q68: Should business logic live in deserializer?

Prefer minimal transformation only. Keep business validation in service/validator layer for clarity and reuse. parse value in deserializer, validate rules elsewhere.

Q69: How to test custom serializer/deserializer?

Round-trip and edge-case tests. Verify valid inputs, invalid inputs, null handling, and backward compatibility. object -> JSON -> object equality checks.

Q70: Custom mapping golden rule?

Be explicit and predictable. JSON contracts should be boring and stable, not surprising. fixed field names and deterministic formats.


Performance and Large Payload Handling

Q71: Is Jackson fast enough for most APIs?

Yes. Jackson is highly optimized; bottlenecks are often elsewhere (I/O, DB, network). response latency mostly DB-bound, not JSON-bound.

Q72: When use Jackson streaming API?

Very large payloads or memory-sensitive processing. Streaming reads/writes incrementally, avoiding full in-memory object trees. processing huge JSON array linearly.

Q73: Data binding vs streaming tradeoff?

Data binding easier; streaming more memory-efficient. Prefer data binding for normal payloads; streaming for scale-critical paths. export millions of records with generator.

Q74: What is ObjectReader/ObjectWriter benefit?

Reusable, preconfigured read/write objects. Can improve clarity and minor performance by avoiding repeated config. one ObjectWriter for pretty logs, one for compact API output.

Q75: Why avoid huge nested DTO graphs?

Serialization cost and complexity. Large object graphs can cause heavy memory use and recursion issues. bidirectional entity references causing deep trees.

Q76: How to avoid infinite recursion in JSON?

Use DTO separation or Jackson reference annotations. Bidirectional relations (parent-child-parent) need explicit handling. @JsonManagedReference / @JsonBackReference.

Q77: Should you serialize JPA entities directly?

Usually no. Lazy loading, recursion, and accidental field exposure are common risks. entity graph triggers unexpected DB queries during serialization.

Q78: Why compact JSON sometimes preferred?

Less bandwidth and faster transfer. Pretty JSON is great for humans, compact JSON for production traffic. machine-to-machine APIs use compact output.

Q79: Can Jackson handle backpressure?

Not by itself. Backpressure is transport/reactive concern; Jackson handles parsing/serialization step. reactive stream controls flow, Jackson maps chunks.

Q80: Performance best-practice line?

Measure first, optimize targeted hotspots only. Don’t over-engineer streaming/custom handlers without profiling evidence. use profiler before rewriting mapping layer.


Security Considerations

Q81: Why is JSON parsing security-relevant?

Untrusted input can trigger vulnerabilities or resource abuse. Large/deep payloads, polymorphic misuse, and unsafe logging are common risk areas. maliciously deep JSON causing heavy parse cost.

Q82: What is polymorphic deserialization risk?

Unsafe type handling can lead to gadget-based attacks. Never enable permissive default typing blindly on untrusted data. restrict allowed subtypes explicitly.

Q83: Is enabling default typing always safe?

No. It can open attack vectors if arbitrary classes are deserialized. avoid broad global default typing for external payloads.

Q84: How to harden Jackson input handling?

Limit payload size/depth and use strict DTOs. Combine parser limits, validation, and controlled type mapping. reject payload > max size at gateway/app layer.

Q85: Why avoid exposing internal exception details?

Information leakage risk. Detailed stack/class info helps attackers and confuses clients. return generic 400 with safe message.

Q86: Should secrets be serialized?

No. Mark sensitive fields ignored/masked and separate internal models from API DTOs. never output passwordHash/apiKey.

Q87: Input validation position with Jackson?

After successful deserialization. Parsing ensures structural validity; validation enforces business/safety rules. bean validation annotations on DTO.

Q88: Safe logging rule for JSON payloads?

Log minimal and redact sensitive fields. Operational visibility must not violate privacy/security policies. mask email/token before writing logs.

Q89: Why contract whitelisting is safer?

Accept only known fields/types. Reduces attack surface and unexpected behavior from extra input. strict DTO rather than Map<String,Object> for external APIs.

Q90: Security best-practice one-liner?

Treat all external JSON as untrusted input. Parse carefully, validate strictly, and expose minimal output. strict DTO + validation + sanitized errors.


Spring Boot + Jackson Practical

Q91: How is Jackson used in Spring Boot by default?

Auto-configured for request/response JSON conversion. Spring’s HttpMessageConverters use ObjectMapper behind the scenes. @RequestBody and @ResponseBody serialization.

Q92: How to customize global ObjectMapper in Spring?

Define/configure mapper bean or Jackson2ObjectMapperBuilder. Centralized config ensures consistent behavior across controllers. global NONNULL + JavaTimeModule.

Q93: @JsonIgnore vs @JsonView in APIs?

Ignore removes field always; JsonView controls per-view exposure. JsonView can support role/context-based payload shaping but adds complexity. public vs internal response view.

Q94: How to return custom JSON error body in Spring?

Use @ControllerAdvice with exception handlers. Keeps error contract consistent for parse/validation/business failures. standardized ApiError response object.

Q95: Why avoid entity exposure in Spring controllers?

Contract and security risks. DTO boundary prevents lazy loading surprises and field leaks. map entity -> response DTO layer.

Q96: How to test Jackson behavior in Spring?

Unit + slice/integration tests with ObjectMapper. Validate schema stability, date formats, and error handling. MockMvc assert JSON path fields.

Q97: What is @JsonComponent?

Spring shortcut for registering custom serializers/deserializers. Useful for Spring-managed custom JSON behavior. custom serializer bean auto-discovered.

Q98: How to exclude null fields globally in Spring?

configure inclusion NONNULL. Reduces payload size/noise while keeping contract explicit. spring.jackson.default-property-inclusion=nonnull

Q99: Why keep JSON contract versioning strategy?

Prevent client breakage. Favor additive changes; use versioning when breaking changes are needed. v1 and v2 response DTOs.

Q100: Spring + Jackson golden rule?

Centralize config and keep DTO contracts explicit. Consistency is more important than clever per-endpoint customization. one mapper policy, many predictable endpoints.


Interview-Focused

Q101: “Why Jackson over Gson?”

Rich ecosystem, strong performance, broad framework support. Jackson’s modules, annotations, streaming, and Spring integration make it dominant in enterprise Java. JavaTime + Kotlin + XML modules available.

Q102: “How do you handle unknown fields in production APIs?”

Usually tolerate for forward compatibility. Policy depends on contract strictness; public APIs often ignore unknowns. @JsonIgnoreProperties(ignoreUnknown = true) for inbound DTO.

Q103: “How do you prevent JSON contract regressions?”

Contract tests and snapshot/schema assertions. Automated tests catch accidental field rename/type/format changes. API test asserting date format and field names.

Q104: “How to deserialize generic types safely?”

TypeReference/JavaType. Avoid raw types to prevent runtime cast issues and hidden map fallback. new TypeReference<List<OrderDto>>() {}

Q105: “How to handle date/time across microservices?”

Standardize on ISO-8601 + UTC policy. Consistent serialization avoids timezone drift bugs between services. Instant serialized with Z.

Q106: “How do you optimize Jackson performance?”

Reuse mapper, avoid unnecessary conversions, profile. Streaming only for truly large payload scenarios. remove object->json->object roundtrips in hot paths.

Q107: “How do you secure Jackson deserialization?”

Restrict types and validate inputs. Avoid permissive polymorphism and enforce strict DTO boundaries. no global default typing on external payloads.

Q108: “JsonNode or POJO mapping?”

POJO for stable schema, JsonNode for dynamic payloads. Mixed approach is common: node for envelope, POJO for payload body. dynamic metadata + typed business section.

Q109: “Custom serializer or annotation config?”

Annotation/config first; custom serializer when necessary. Prefer simpler maintainable options before custom code. @JsonFormat solves many date formatting needs.

Q110: “Most common Jackson production bug?”

Inconsistent mapper configuration across modules. Centralized config and tests prevent format/drift issues. one module writes timestamps, another writes ISO strings.


Final Mastery Checklist

Q111: Can you explain serialization/deserialization clearly?

If yes, foundation is strong. This is core to API reliability and integration correctness. request JSON -> DTO -> response JSON flow.

Q112: Can you configure ObjectMapper centrally and safely?

If yes, consistency improves. Central policies reduce endpoint drift and production surprises. one shared Spring mapper bean.

Q113: Can you handle generics without raw-type pitfalls?

If yes, typing maturity is strong. TypeReference use prevents runtime cast and map fallback issues. parse list/map nested DTOs safely.

Q114: Can you map date/time with explicit timezone policy?

If yes, distributed correctness improves. Time ambiguity is a major integration bug source. Instant UTC everywhere.

Q115: Can you design safe error handling for bad JSON?

If yes, client/dev experience improves. Consistent 400 responses + sanitized logs are essential. controller advice for parse exceptions.

Q116: Can you avoid entity exposure and use DTO contracts?

If yes, API stability/security improve. DTO boundaries decouple persistence from external contract. entity->DTO mapper layer.

Q117: Can you reason about Jackson security risks?

If yes, production safety improves. Untrusted input + permissive typing is dangerous. strict subtype control and validation.

Q118: Can you test JSON contracts effectively?

If yes, regressions drop. Tests should lock schema, formats, and error behavior. MockMvc JSON path assertions.

Q119: Can you choose between POJO/tree/streaming models properly?

If yes, design is practical and efficient. Right model per use case avoids complexity/perf issues. stream huge exports, POJO for normal API bodies.

Q120: Final principle for Jackson in backend systems?

Keep JSON contracts explicit, stable, and secure. Jackson is powerful—use that power with consistency, validation, and clear boundaries. centralized config + DTO-first API design.