Git Product home page Git Product logo

jackson-core's Introduction

Overview

This project contains core low-level incremental ("streaming") parser and generator abstractions used by Jackson Data Processor. It also includes the default implementation of handler types (parser, generator) that handle JSON format. The core abstractions are not JSON specific, although naming does contain 'JSON' in many places, due to historical reasons. Only packages that specifically contain word 'json' are JSON-specific.

This package is the base on which Jackson data-binding package builds on. It is licensed under Apache License 2.0.

Alternate data format implementations (like Smile (binary JSON), XML, CSV, Protobuf, and CBOR) also build on this base package, implementing the core interfaces, making it possible to use standard data-binding package regardless of underlying data format.

Project contains versions 2.0 and above: source code for earlier (1.x) versions can be found from Jackson-1 github repo.

Status

Type Status
Build (CI) Build (github)
Artifact Maven Central
OSS Sponsorship Tidelift
Javadocs Javadoc
Code coverage (2.16) codecov.io
CodeQ (ClusterFuzz) Fuzzing Status
OpenSSF Score OpenSSF Scorecard

Get it!

Maven

Functionality of this package is contained in Java package com.fasterxml.jackson.core.

To use the package, you need to use following Maven dependency:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>${jackson.version.core}</version>
</dependency>

or download jars from Maven repository or links on Wiki. Core jar is a functional OSGi bundle, with proper import/export declarations.

Package has no external dependencies, except for testing (which uses JUnit).

Non-Maven

For non-Maven use cases, you download jars from Central Maven repository.

Core jar is also a functional OSGi bundle, with proper import/export declarations, so it can be use on OSGi container as is.

Jackson 2.10 and above include module-info.class definitions so the jar is also a proper Java module (JPMS).

Jackson 2.12 and above include additional Gradle 6 Module Metadata for version alignment with Gradle.


Use it!

General

Usage typically starts with creation of a reusable (and thread-safe, once configured) JsonFactory instance:

// Builder-style since 2.10:
JsonFactory factory = JsonFactory.builder()
// configure, if necessary:
     .enable(JsonReadFeature.ALLOW_JAVA_COMMENTS)
     .build();

// older 2.x mechanism, still supported for 2.x
JsonFactory factory = new JsonFactory();
// configure, if necessary:
factory.enable(JsonReadFeature.ALLOW_JAVA_COMMENTS);

Alternatively, you have an ObjectMapper (from Jackson Databind package) handy; if so, you can do:

JsonFactory factory = objectMapper.getFactory();

Usage, simple reading

All reading is by using JsonParser (or its sub-classes, in case of data formats other than JSON), instance of which is constructed by JsonFactory.

An example can be found from Reading and Writing Event Streams

Usage, simple writing

All writing is by using JsonGenerator (or its sub-classes, in case of data formats other than JSON), instance of which is constructed by JsonFactory:

An example can be found from Reading and Writing Event Streams

Processing limits

Starting with Jackson 2.15, Jackson has configurable limits for some aspects of input decoding and output generation.

Implemented limits are:

  • Length are expressed in input/output units -- bytes or chars -- depending on input source
  • Defined as longest allowed length, but not necessarily imposed at 100% accuracy: that is, if maximum allowed length is specified as 1000 units, something with length of, say 1003 may not cause exception (but 1500 would typically do)
  • Defined using new StreamReadConstraints / StreamWriteConstraints classes, configurable on per-JsonFactory basis
  • Main focus is to reduce likelihood of excessive memory usage/retention and/or processing costs; not validation

Input parsing limits

  • Maximum Number token length (2.15+): (see #815)
    • Default: Maximum 1000 for both integral and floating-point numbers.
  • Maximum String value length (2.15+): (see #863)
    • Default: 20_000_000 (20 million) (since 2.15.1; 2.15.0 had lower limit, 5 million)
  • Maximum Input nesting depth (2.15+): (see #943)
    • Default: 1000 levels
  • Maximum Property name length (2.16+): (see #1047)
    • Default: 50,000
  • Maximum Document length (2.16+): (see #1046)
    • Default: Unlimited (-1)

Output generation limits

  • Maximum Output nesting depth (2.16+): (see #1055)
    • Default: 1000 levels

Re-configuring limits

You can change per-factory limits as follows:

JsonFactory f = JsonFactory.builder()
  .streamReadConstraints(StreamReadConstraints.builder().maxDocumentLength(10_000_000L).build())
  .streamReadConstraints(StreamReadConstraints.builder().maxNumberLength(250).build())
  .streamWriteConstraints(StreamWriteConstraints.builder().maxNestingDepth(2000).build())
  .build();

Error Report Configuration

Starting with Jackson 2.16, Jackson offers configurable behavior around error-reporting.

Currently supported configuration options are:

  • maxErrorTokenLength : Maximum length of token to include in error messages (2.16+): (see #1066)
  • maxRawContentLength : Maximum length of raw content to include in error messages (2.16+): (see #1066)

... see Example section below.

Example

JsonFactory f = JsonFactory.builder()
 .errorReportConfiguration(ErrorReportConfiguration.builder()
   .maxErrorTokenLength(1004)
   .maxRawContentLength(2008)
   .build()
 ).build();

Compatibility

JDK

Jackson-core package baseline JDK requirement:

  • Versions 2.0 - 2.13 require JDK 6
  • Versions 2.14 and above require JDK 8

Android

List is incomplete due to recent addition of compatibility checker.

  • 2.13: Android SDK 19+
  • 2.14 and above: Android SDK 26+

for information on Android SDK versions to Android Release names see Android version history


Release Process

Starting with Jackson 2.15, releases of this module will be SLSA compliant: see issue #844 for details.

Release process is triggered by

./release.sh

script which uses Maven Release plug-in under the hood (earlier release plug-in was directly invoked).


Support

Community support

Jackson components are supported by the Jackson community through mailing lists, Gitter forum, Github issues. See Participation, Contributing for full details.

Enterprise support

Available as part of the Tidelift Subscription.

The maintainers of jackson-core and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.


Further reading

Differences from Jackson 1.x

Project contains versions 2.0 and above: source code for the latest 1.x version (1.9.13) is available from FasterXML/jackson-1 repo (unmaintained).

Note that the main differences compared to 1.0 core jar are:

  • Maven build instead of Ant
  • Annotations carved out to a separate package (that this package depends on)
  • Java package is now com.fasterxml.jackson.core (instead of org.codehaus.jackson)

Links

  • Project Wiki has JavaDocs and links to downloadable artifacts
  • Jackson (portal) has links to all FasterXML-maintained "official" Jackson components
  • Jackson Docs is the portal/hub for all kinds of Jackson documentation

jackson-core's People

Contributors

arnaudroger avatar asoldano avatar bhamiltoncx avatar christophercurrie avatar cowtowncoder avatar dependabot[bot] avatar digulla avatar goncalossilva avatar jhaber avatar joohyukkim avatar lislon avatar lokeshn avatar mariofusco avatar marschall avatar mikaelstaldal avatar philzen avatar pjfanning avatar pnacht avatar qpliu avatar rfoltyns avatar sleberknight avatar tatu-at-datastax avatar tatu-at-salesforce avatar therealhaui avatar timo-a avatar uhhhh2 avatar valery1707 avatar xtonik avatar yawkat avatar yeikel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jackson-core's Issues

JsonFactory._optimizedStreamFromURL() fails on file URLs with spaces

This method has special handling for file URLs - once it detects them, it does this:

return new FileInputStream(url.getPath());

This fails with FileNotFoundException if the path contains spaces, encoded as usual in URLs with %20. And it probably also fails on any other sort of percent-encoded character.

(In case you're wondering, calls to ...getContextClassLoader().getResource() are a frequent source of such URLs, at least in my case.)

Suggested fix:

return new FileInputStream(URLDecoder.decode(url.getPath(), "UTF-8"));

RFE: New JsonMappingException subclasses

Referencing this thread:
http://jackson-users.ning.com/forum/topics/avoid-exposing-implementation-details-in-jsonmappingexeption

Here's the situation:

A user gives my application JSON w/ an improperly formatted Date string. This generates an IllegalArgumentException in DateTime, which is then wrapped in a JsonMappingException with a message like the following:

Invalid format: "badDateString" (through reference chain: com.example.MyPojo["date"]).

I'd like to provide the user an informative error message that gives some idea of the cause, however I don't want to expose the internal details of my POJO. There doesn't seem to be a good way to do this currently.

It would be ideal if Jackson provided additional subclasses of JsonMappingException (as has been done with UnrecognizedPropertyException) that could provide additional contextual details that would allow the exception to be better handled and reported. (E.g. it can be difficult to determine if the exception is the result of unexpected JSON or JSON->POJO coding errors).

Thanks!

Replace use of std String.hashCode() with safer alternative

There have been some attacks (DoS) that make use of collisions in String.hashCode() values (or at least their low-bits collisions).
The one place where this matters most is in handling of symbol table: although Jackson actually does not directly use String.hashCode(), internal calculation is along the same lines.

This should be changed by, for example:

  • Using a non-constant seed value for calculation starting point; this could use system time as base, and needs to be something that varies between different runs
  • Append or prepend String length
  • Perhaps even use different multiplier during different runs? (31 vs 37 vs 39)

Care needs to be taken as this is one of more performance critical paths.

Add checking of maximum collision lengths for symbol tables

In addition to [Issue-21](try to prevent hash collision attacks), it seems prudent to also add fallback verification to throw exception in case abnormal number of hash collisions is detected. In case where no collision attacks exist, this should have no measurable impact; but just in case new attacks are formulated, they would get caught.

NullPointerException from TypeFactory._constructType

When the same module is registered twice, a NullPointerException will be thrown during json parsing.

For example,

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(DefaultScalaModule);
mapper.registerModule(DefaultScalaModule);

InternCache blocks performance more than it helps

jackson is used in the riak-java-client and my java tool which does a conversion of mysql data into riak db had a lot of complete lockdowns during conversion. The tools starts about 200 threads which do the conversion in parallel. Doing several thread dumps quickly revealed the threads were waiting a lot to get into the synchronized "intern"-Method in your InternCache.

I removed the InternCache and run the script again, this time the performance improved a lot and the strange lockdowns were gone. Possibly at a cost of higher cpu-load, I didn't measure that.

I doubt this InternCache is of any use because of the need of synchronisation. Maybe doing it as ThreadLocal would help. The way it is currently done is critical for environments with a lot of threads.

Strange error message (incomplete?) when attempting to read some kinds of malformed JSON trees (2.1.4)

This program:

    public static void main(final String... args)
        throws IOException
    {
        try {
            new ObjectMapper().reader().readTree("treu");
        } catch (JsonProcessingException e) {
            System.out.println(e.getOriginalMessage());
        }
    }

prints out:

Unrecognized token 'treu': was expecting

And nothing else. Generally speaking, it happens each time a JSON boolean or null is input which is at least the correct length but mispelled or followed by unexpected letters (for instance, truez also outputs the same).

It does not happen though if the value does not have the expected length (ie, tru, nul, in which case the message is Unexpected end-of-input in a value).

Jackson 2.x License

I have been back and forth over the Jackson 2.x source, binary and documentation and I can find no mention of the license used. Jackson 1.x was dual-licensed as LGPL and ASL, but had separate downloads for each. Does Jackson 2.x have a similar license, and where can I find the license information?

java.lang.OutOfMemoryError during deserialization

The stacktrace has been attached at the bottom. Known issue ?

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.fasterxml.jackson.core.util.TextBuffer._charArray(TextBuffer.java:705)
at com.fasterxml.jackson.core.util.TextBuffer.expand(TextBuffer.java:664)
at com.fasterxml.jackson.core.util.TextBuffer.append(TextBuffer.java:468)
at com.fasterxml.jackson.core.io.SegmentedStringWriter.write(SegmentedStringWriter.java:67)
at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator._flushBuffer(WriterBasedJsonGene
rator.java:1799)
at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator._writeString(WriterBasedJsonGene
rator.java:975)
at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator.writeString(WriterBasedJsonGener
ator.java:436)
at com.fasterxml.jackson.databind.ser.std.StringSerializer.serialize(StringSerializer.java:3
6)
at com.fasterxml.jackson.databind.ser.std.StringSerializer.serialize(StringSerializer.java:1
)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter
.java:464)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerB
ase.java:504)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:117)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedLi
stSerializer.java:94)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedLi
stSerializer.java:1)
at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerB
ase.java:150)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter
.java:464)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerB
ase.java:504)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:117)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedLi
stSerializer.java:94)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedLi
stSerializer.java:1)
at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerB
ase.java:150)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter
.java:464)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerB
ase.java:504)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:117)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedLi
stSerializer.java:94)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedLi
stSerializer.java:1)
at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerB
ase.java:150)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter
.java:464)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerB
ase.java:504)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:117)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedLi
stSerializer.java:94)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedLi
stSerializer.java:1)

Add support for non-blocking ("async") JSON parsing

(migrated from http://jira.codehaus.org/browse/JACKSON-39 -- note, high vote count)


(suggested by Dimitri M on user list)

There are use cases where it'd be good to be able to feed input to parser, instead of trying to provide an input stream for parser to read from. This would cover use cases where input comes in chunks; for example, part of logical document in one chunk, then after a delay (perhaps in a separate request) another one and so forth. In these cases it may be difficult to implement InputStream (Reader etc) abstraction; instead, it would be better if application could feed (push) data to parser.
But if so, parser must be able to indicate cases where no data is YET available (but may become available).

This is similar to how Aalto Xml processor (http://www.cowtowncoder.com/hatchery/aalto/index.html) operatesd in its async mode. However, since Json is much simple format than xml, implementation might be simpler.

Based on my experiences with Aalto, implementation is a non-trivial thing however. One problem is that even UTF-8 decoding needs to be somewhat aware of chunk boundaries, so in the end a separate parser may be required: this because current parser uses blocking to handle these split cases. A smaller problem is that of indicating "not-yet-available" case โ€“ this can probably be handled by introducing a new member in JsonToken enumeration.

Remove VERSION.txt files from Jackson JARs

I'm currently using a library which depends on jackson-core.jar, jackson-databind.jar and jackson-annotations.jar in an Android project. When looking at the project's APK contents, I realized there are files at

project.apk/com/fasterxml/jackson/core/json/VERSION.txt
project.apk/com/fasterxml/jackson/databind/cfg/VERSION.txt

It seems Android's apkbuilder tool does not filter out text files from the source tree before packaging the APK (although it filters out several other files, see checkFileForPackaging()). I'm not sure the VERSION.txt files are there on purpose after all, as jackson-annotations.jar comes without it. So I'd like to kindly ask you to consider removing the VERSION.txt from the distribution JARs, or to place it e.g. in the META-INF directory which gets filtered by the ApkBuilder tool.

(I'm filing this issue for jackson-core only, although it affects jackson-databind, too.)

UTF8StreamJsonParser.nextFieldName() fails to compare field names straddling the _inputBuffer boundary.

It seems like UTF8StreamJsonParser.nextFieldName() does not work properly when a field name straddles the 4000 byte boundary of _inputBuffer.

Test-case below:

import static org.junit.Assert.*;

import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;

import org.junit.Test;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.SerializedString;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestJackson {
    // ROUND.length() * 223 == 4014; UTF8StreamJsonParser._inputBuffer will end with "f" in "fieldName".
    private static final int TESTROUNDS = 223;
    private static final String TESTJSON = "{ \"fieldName\": 1 }";

    private static final JsonFactory FACTORY = new JsonFactory(new ObjectMapper());

    private static JsonParser parser(String json) throws Exception {
        return FACTORY.createParser(new ByteArrayInputStream(json.getBytes(Charset.forName("utf-8"))));
    }

    private static String rounds(String json, int rounds) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < rounds; i++) {
            sb.append(json);
        }
        return sb.toString();
    }

    @Test
    public void testNextFieldName() throws Exception {
        SerializableString fieldName = new SerializedString("fieldName");

        JsonParser parser = parser(rounds(TESTJSON, TESTROUNDS));
        for (int i = 0; i < TESTROUNDS - 1; i++) {
            assertEquals(JsonToken.START_OBJECT, parser.nextToken());

            // These will succeed
            assertTrue(parser.nextFieldName(fieldName));

            parser.nextLongValue(-1);
            assertEquals(JsonToken.END_OBJECT, parser.nextToken());
        }

        assertEquals(JsonToken.START_OBJECT, parser.nextToken());

        // This will fail
        assertTrue(parser.nextFieldName(fieldName));
    }
}

Infinite loop in nextFieldName when parsing from byte[]

jackson-core 2.1.0

Bellow is the unit test, the fourth test fails with timeout indicating an infinite loop. The test is trying to parse a simple JSON object string converted to byte array. It works for:

{"field":"value"}

but fails for:

{"field"<space_here!>:"value"}

The loop starts in UTF8StreamJsonParser._skipColon() which keeps calling _skipCR().

import junit.framework.Assert;

import java.io.IOException;
import java.nio.charset.Charset;

import org.junit.Test;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.io.SerializedString;

public class JsonParserNextFieldNameTest
{
    private static final JsonFactory JSON_FACTORY = new JsonFactory();

    private static final String JSON = "{\"field\":\"value\"}";
    private static final String JSON_WITH_SPACE_BEFORE_COLON = "{\"field\" :\"value\"}";

    @Test
    public void parseJsonAsString() throws IOException
    {
        parse(JSON, false);
    }

    @Test
    public void parseJsonAsBytes() throws IOException
    {
        parse(JSON, true);
    }

    @Test
    public void parseJsonWithSpaceAsString() throws IOException
    {
        parse(JSON_WITH_SPACE_BEFORE_COLON, false);
    }

    @Test(timeout = 5000L)
    public void parseJsonWithSpaceAsBytes() throws IOException
    {
        parse(JSON_WITH_SPACE_BEFORE_COLON, true);
    }

    private void parse(String json, boolean asBytes) throws IOException
    {
        JsonParser jp = asBytes ? JSON_FACTORY.createParser(json.getBytes(Charset.forName("UTF-8"))) : JSON_FACTORY.createParser(json);
        Assert.assertEquals(JsonToken.START_OBJECT, jp.nextToken());
        Assert.assertTrue(jp.nextFieldName(new SerializedString("field")));
    }
}

Add a method in JsonGenerator for writing Object Id value/property?

Since some data formats (YAML, for example) have their own notions of Object Identity handling, it would make sense to push bit more semantical information through lower level abstractions. One way to do this would be to add new methods to use when serializing Object ids and references.

Add 'JsonGenerator.writeString(Reader r, int charLength)'

Current 'writeString()' method requires text value to be passed in its entirety. This may not work well with larger payloads; so we should an alternative method where one can define source for text, used for incremental/streaming read+write.
In addition to Reader, it should be possible to indicate exact number of bytes to include; this because some formats (not JSON however!) require such information to be written before data, or used for initializing write. It should be possible to pass marker value -1 to indicate "not known": not all generators are required to support it, however.

If length is indicated, it is an error for Reader to provide less data (more is ok; generator just will not read anything beyond indicated amount).

Make `JsonFactory` Serializable

Usually we don't care whether non-persisted objects are Serializable. But in case of JsonFactory there are reasons to do this, for certain platforms. Specifically, on mobile platforms like Android, "freezing state" may require flushing out lots of things. And re-creating those things, conversely, may be more costly than would simple de-serialization be.

To see if this could work, it would be good to see how easy it'd be to make JsonFactory (which is the entry point to core streaming api) java.io.Serializable. And if that works, continue up the stack to databinding.

Improve @JsonView flexibility

I'm struggling with a problem that is probably common for people that extensively use @JSONVIEW. Since only one view can be active at any one time, and jsonview classes are singly-inherited, the facility is very tightly constrained. There are a lot of cases where I need to define multiple views: "Show me the properties relevant to green administrators and the fields relevant to blue administrators", where these are not perfect subsets.

From an API perspective, one solution would be to allow json views to be defined by interfaces and thus enable multiple inheritance. Alternatively, just allow multiple views to be specified - although this raises the question of AND vs OR.

P.S. Thank you thank you THANK YOU for moving development to github!

Add 'readBinaryValue()' method in JsonParser

Current JsonParser.getBinaryValue() requires reading of the whole value (base64 decoded text for JSON; may be native for other formats) and return it as a byte[]. While convenient, this is not scalable for larger binary payloads.

As an alternative method, there should be something like:

boolean readBinaryValue(OutputStream out);

which would read binary content (decoding if necessary), and pass it using given OutputStream; but possibly in separate chunks, without aggregating it. This allows caller to do incremental processing and avoid potentially big temporary memory usage.

In addition, for non-blocking parser implementations, this method could do partial decoding, meaning that it would only parse part of binary payload; return value indicating whether full contents (true) or partial content (false) was processed.

JsonParser.getTokenLocation() doesn't update after field names.

There's a unit test to repro the issue below. Basically, when you're on a FIELD_NAME token, if you call getTokenLocation() and then nextToken() and then getTokenLocation() again, you'll get the same location for both calls to getTokenLocation(), even though you've advanced to a new token.

The issue seems to be the _nextToken logic in ReaderBasedJsonParser and UTF8StreamJsonParser. When calling nextToken() on a FIELD_NAME, it calls _nextAfterName(), which updates _currToken but doesn't update _tokenInputRow and _tokenInputCol for the new token's location.

I started to try to fix it, but the _nextToken logic is spread across so much code that it looked like it'd be a pretty major surgery. Not something I'm willing to do at this point. :-)

public void testTokenLocationAfterFieldName() throws Exception
{
    _testTokenLocationAfterFieldName(false);
    _testTokenLocationAfterFieldName(true);
}

private void _testTokenLocationAfterFieldName(Boolean useStream) throws Exception
{
    final String DOC = "{\"name\":123}";
    JsonFactory jf = new JsonFactory();
    JsonParser jp = useStream ?
            jf.createJsonParser(new ByteArrayInputStream(DOC.getBytes("UTF-8")))
            : jf.createJsonParser(new StringReader(DOC));

    assertEquals(JsonToken.START_OBJECT, jp.nextToken());
    assertEquals(JsonToken.FIELD_NAME, jp.nextToken());
    assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
    assertEquals(1, jp.getTokenLocation().getLineNr());
    assertEquals(9, jp.getTokenLocation().getColumnNr());
    jp.close();
}

TypeFactory.fromType(Type type, Type... typeParameters)

This will allow users to specify multiple type parameters, as well it will allow them to easily mix simple (URL) and compound type (List<URL>) parameters with ease. Finally, by having JavaType extend java.lang.reflect.Type we will be able to tunnel JavaType through Jersey's Client.get(Type) method.

See issue #41 for more information.

Copy String chars to char array by TextBuffer fails with ArrayIndexOutOfBoundsException

Related jackson-core version is 2.0.4.

In com.fasterxml.jackson.core.util.TextBuffer line 498 expand( len ) is called which results in setting the _currentSegment to MAX_SEGMENT_LEN, even when the segment size is supposed to grow.

Thanks in advance for your support with this!

Related test is given below:


package europass.ewa.services.conversion.xml;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import java.io.IOException;
import java.util.Random;

import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class BytesToXmlTest{
    
    
    @Test
    public void write256KBData() throws JsonGenerationException, JsonMappingException, IOException {
        testWriteData(256);
    }
    
    @Test( expected=JsonMappingException.class )
    public void write384KBData() throws JsonGenerationException, JsonMappingException, IOException {
        testWriteData(384);
    }

    public void testWriteData(int kb) throws JsonGenerationException, JsonMappingException, IOException {
        Random r = new Random(1);
        Data data = new Data();
        data.bytes  = new byte[1024*kb];
        r.nextBytes(data.bytes);
        String xml = new XmlMapper().writeValueAsString(data);
        assertThat(xml, is(notNullValue()));
    }


    public static class Data {
        
        @JsonProperty
        byte[] bytes;
    }
}

Centralize annotation validation

Please centralize annotation validation so serializers/deserializes can invoke the method once at startup. This will ensure we throw exceptions instead of ignoring errors silently. See issue #41 for background information.

PrettyPrinter interface makes it hard/impossible to tweak the pretty printing

I have been trying to implement my own pretty printing for json output but due to the API, I cannot find a way to detect that I am going to output an empty array or an empty map and act accordingly.

The issue is that the api PrettyPrinter.writeStartObject(JsonGenerator jg) does not provide the number of entries (it is provided only on writeEndObject).

I would like to output:

  {
    "a": {
      "b1": 3,
      "b2": 4,
      },
   "c": {}
  }

but cannot find a way with the api to output an empty map ({}) this way when there are no elements since I don't know until the end.

Annotations should be validated (like reporting error for using @JsonWrapped on array)

I'd like to transform:

{
  "singleKey":
  [
    "value1",
    "value2"
  ]
}

into:

[
    "value1",
    "value2"
]

I tried using @JsonUnwrapped on the List in question but Jackson ignores it silently. I assume this is what is meant by the Javadoc: "can not unwrap JSON arrays using this mechanism". I have three questions:

  1. Is this what is meant by the Javadoc?
  2. If so, can we add this feature?
  3. Is there a workaround I can use?

Add JsonParser.getFieldIndex(); an "unmappable" field name

We will need a way to indicate property ids that are based on ints as opposed to Strings, for formats like Thrift and Protobuf (and probably others). For this a new method is probably needed.
Also, it would make sense to additionally return some kind of marker for existing String-based method(s) (getCurrentName()); while value may be something like empty String, it'd be good to be able to use identity comparison.

Since this is an API change, needs to go in 2.1

Include javadoc jar in Maven repository

I see in the Maven repo jackson-core-asl-1.9.6.jar and jackson-core-asl-1.9.6-sources.jar, but not jackson-core-asl-1.9.6-javadoc.jar. The majority of packages in the Maven Central repository include javadoc jars. A javadoc jar can be useful for tools like Eclipse that make use of these jars. Also, when using the Play 2 framework eclipsify task, I get numerous warnings that jackson-core-asl-1.9.6-javadoc.jar cannot be found, which is pretty annoying.

add 'writeBinary(InputStream, int)' method in JsonGenerator

Current 'writeBinary()' method requires binary data to be passed as a byte array. This may not work well with larger payloads; so we should an alternative method where one can define source for binary data.
In addition to InputStream, it should be possible to indicate exact number of bytes to include; this because some formats (not JSON however!) require such information to be written before data, or used for initializing write. It should be possible to pass marker value -1 to indicate "not known": not all generators are required to support it, however.

JsonParser: add "getTextAsBytes()" that will return text as UTF-8 encoded bytes

(moved from http://jira.codehaus.org/browse/JACKSON-447)

(request by David Yu, via mailing list)


Feature request:
byte[] raw = JsonParser.getRawString();

Kinda like the raw getBinaryValue() except that the value was never b64 encoded (e.g a utf8 string)


(Tatu's comments)

I think a good name would be "getTextAsBytes()", to follow existing naming convention. I think it is ok to only expose UTF-8 encoded Strings, given that JSON itself only supports Unicode encodings.

One open question is whether there should be complementary method(s) that would take a byte array (or buffer) to append/write string into. But maybe it's best to start simple and improve things over time.

...

Sounds like David was hoping to get contents before replacing escaped codes (probably to pass through JSON output with minimal changes). This is unfortunately very difficult to do in general case, so I will not consider this for inclusion with 1.7.0. Perhaps a solution can be found in future; leaving this issue open still.

JsonProcessingException doesn't let you access original message

The JsonProcessingException class doesn't give you access to the original message string.

It looks like the way to get the message is via 'getMessage()' which also includes location information.

One use case where having the raw message is useful is in a GUI. You want to use the location object to figure out where the error is, and then use the message string to display the error message. It's ugly to have the location repeated in the message string.

My use case has to do with prepending the "logical path" to an error message (things like "field 'servers', array index 4". At every step in my object processing, I catch JsonParseException, prepend the current "logical path" to the error message and rethrow. Unfortunately, I have no access to the original message so I do a super hack where I search for the last occurrence of " at " and strip out everything after that :-\

Add a feature in JsonParser to verify that no duplicate field values are given

Although JSON specification does not make duplicate Object values strictly illegal (behavior is undefined I think), their existence is problematic, as behavior is not specified.
On the other hand, checking for duplicates adds non-trivial amount of cost which for valid content is pure overhead.

So it would probably make sense to add a feature to let users request that duplicate detection is enabled, and reported as an exception. For bonus points it should be possible to dynamically enable this via ObjectMapper (from databind) as well, since this will allow per-request handling (as opposed to JsonParser feature which may be more difficult to set).

Make it possible to suppress the "separating space" when writing multiple objects with the same json generator

04:55:30 PM) henning_asf: https://gist.github.com/3173456
(04:56:19 PM) tatu_seaforce: one thing is that you can avoid JsonGenerator itself, pass Writer, write linefeed separately
(04:56:25 PM) tatu_seaforce: but I don't know if that makes much difference
(04:56:32 PM) tatu_seaforce: (under the hood, will create new one anyway in that case)
(04:57:08 PM) tatu_seaforce: you could implement mostly bogus PrettyPrinter also, to suppress that space
(04:57:28 PM) tatu_seaforce: or, if you are using 2.0.x, you could file an RFE to suppress that space for JsonGenerator via new JsonGenerator.Feature
(04:57:43 PM) tatu_seaforce: think it should be easy to add. I am trying to finalize 2.1 soon
(04:58:30 PM) henning_asf: so the problem is in _verifyValueWrite in the Utf8Generator
(04:59:20 PM) henning_asf: it turns out that the state when starting the second object is "STATUS_OK_AFTER_SPACE" and then it adds a space to the buffer.
(04:59:43 PM) tatu_seaforce: right, idea is that if someone outputs, say, numbers at root context
(04:59:52 PM) tatu_seaforce: it typically needs separator.
(04:59:56 PM) henning_asf: and that one is called from writeStartObject() in the JsonGeneratorBase.
(05:00:02 PM) tatu_seaforce: but, usually people woudl probably want a linefeed instead
(05:00:20 PM) henning_asf: yes. If I could set the separator, my world would be perfect (because then I would set the newline as the separator)
(05:00:33 PM) tatu_seaforce: ok. Or empty String to disable it.
(05:00:37 PM) henning_asf: but because I can not do that, I write the newline myself and now I have an annoying space. :-)
(05:00:40 PM) henning_asf: yes, or empty string.
(05:00:44 PM) tatu_seaforce: sounds like a good feature... care to file an issue at github?04:55:30 PM) henning_asf: https://gist.github.com/3173456
(04:56:19 PM) tatu_seaforce: one thing is that you can avoid JsonGenerator itself, pass Writer, write linefeed separately
(04:56:25 PM) tatu_seaforce: but I don't know if that makes much difference
(04:56:32 PM) tatu_seaforce: (under the hood, will create new one anyway in that case)
(04:57:08 PM) tatu_seaforce: you could implement mostly bogus PrettyPrinter also, to suppress that space
(04:57:28 PM) tatu_seaforce: or, if you are using 2.0.x, you could file an RFE to suppress that space for JsonGenerator via new JsonGenerator.Feature
(04:57:43 PM) tatu_seaforce: think it should be easy to add. I am trying to finalize 2.1 soon
(04:58:30 PM) henning_asf: so the problem is in _verifyValueWrite in the Utf8Generator
(04:59:20 PM) henning_asf: it turns out that the state when starting the second object is "STATUS_OK_AFTER_SPACE" and then it adds a space to the buffer.
(04:59:43 PM) tatu_seaforce: right, idea is that if someone outputs, say, numbers at root context
(04:59:52 PM) tatu_seaforce: it typically needs separator.
(04:59:56 PM) henning_asf: and that one is called from writeStartObject() in the JsonGeneratorBase.
(05:00:02 PM) tatu_seaforce: but, usually people woudl probably want a linefeed instead
(05:00:20 PM) henning_asf: yes. If I could set the separator, my world would be perfect (because then I would set the newline as the separator)
(05:00:33 PM) tatu_seaforce: ok. Or empty String to disable it.
(05:00:37 PM) henning_asf: but because I can not do that, I write the newline myself and now I have an annoying space. :-)
(05:00:40 PM) henning_asf: yes, or empty string.
(05:00:44 PM) tatu_seaforce: sounds like a good feature... care to file an issue at github?

Add 'readText()' method in JsonParser

Current JsonParser.getText() requires reading of the whole JSON String value as String.
While convenient, this may not be optimal when processing large payloads.

As an alternative method, there should be something like:

boolean readText(Writer w);

which would read JSON String value, and pass it using given Writer; but possibly in separate chunks, without aggregating it. This allows caller to do incremental processing and avoid potentially big temporary memory usage.

In addition, for non-blocking parser implementations, this method could do partial decoding, meaning that it would only parse part of textual value; return value indicating whether full contents (true) or partial content (false) was processed.

Handle possible security problem with ObjectNode, HashMap, String.hashCode()

(see [https://github.com//issues/21] for related problem)

Given that it is easy to fabricate collisions for String.hashCode() (since JDK's impl allows substring-replacement style attacks very easily), ObjectNode is prone to attacks.
Since JsonParser use has been fixed (Issue-21), it is necessary to simialrly address the issue of use of HashMap with default String hashCode().

The big problem here is the performance: not so much that of cost of calculating hashCode() alone, but lack of caching of that value (JDK aggressively caches hashCode on first access).

We should probably do similar two-part solution here as earlier: make it possible to detect abnormal (super high collision list) cases and error out; but also improve hash code used as much as possible.

UTF8JsonGenerator.writeBinary(InputStream, int) causes infinite loop.

Specific stream length causes infinite loop on UTF8Generator.

Test Code:

ByteArrayOutputStream bytes = new ByteArrayOutputStream();
IOContext ioc = new IOContext(new BufferRecycler(), bytes, true);
JsonGenerator gen = new UTF8JsonGenerator(ioc, 0, null, bytes);

ByteArrayInputStream data = new ByteArrayInputStream(new byte[2000]);
gen.writeBinary(data, 1999);

Patch:

--- a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
@@ -1681,7 +1681,11 @@
         maxRead = Math.min(maxRead, readBuffer.length);

         do {
-            int count = in.read(readBuffer, inputEnd, maxRead - inputEnd);
+            int length = maxRead - inputEnd;
+            if (length == 0) {
+                return inputEnd;
+            }
+            int count = in.read(readBuffer, inputEnd, length);
             if (count < 0) {
                 return inputEnd;
             }

InputStream returns 0 on not reached stream end.

Make `JsonFactory` Serializable

Usually we don't care whether non-persisted objects are Serializable. But in case of JsonFactory there are reasons to do this, for certain platforms. Specifically, on mobile platforms like Android, "freezing state" may require flushing out lots of things. And re-creating those things, conversely, may be more costly than would simple de-serialization be.

To see if this could work, it would be good to see how easy it'd be to make JsonFactory (which is the entry point to core streaming api) java.io.Serializable. And if that works, continue up the stack to databinding.

Add support for 'missing values' in JSON arrays

Got question or request for Feature to be added.

I have json object that does not follow json standard.
Example
[,,"41513053","30120.00",]

I have no control over the json only that I receive it.
I understand why the developers did it. ( to preserve bandwith ).
[null,null,"41513053","30120.00",null]

So I get ' com.fasterxml.jackson.core.JsonParseException: Unexpected
character (',' (code 44)): expected a valid value (number, String,
array, object, 'true', 'false' or 'null')'

It would be a nice feature to except this as null value.
JsonParser.Feature.ALLOW_NULL_EMPTY_VALUES.

Add more methods in TreeNode, to allow some generic traversal

Currently (2.1) TreeNode interface has little actual functionality, and can not be used for traversal. It would make sense to add bit more functionality to allow some level of generic traversal over different implementations. For example:

  • isValueNode(), isContainerNode(), isMissingNode() (and possibly isArray(), isObject()) would allow more convenient type detection (although existing 'asToken()' can in theory be used for the same)
  • size(), get(String) and get(int) should allow traversal of values of structured nodes (array, object).

Add 'JsonFactory.createParser()' and 'JsonFactory.createGenerator()'

One naming change that should have gone in 2.0, but was sadly forgotten is that of making JsonFactory's factory methods more generic. There is no need to emphasize "json" in methods to begin with; and with 2.0, there are many non-JSON backends, so this is becoming bit of an eyesore.

So, with 2.1, we should add methods:

JsonFactory.createParser(...) to replace 'creteJsonParser(...) methods
JsonFactory.createGenerator(...) to replace 'createJsonGenerator(...) methods

and implement them, initially to delegate to old variants in 2.1; and ensure that non-JSON data formats also override methods if and as necessary (usually they override secondary methods which may not be changing).
And with 2.2, old methods should be deprecated, to get application-level code to eventually be upgraded.

We will not be able to remove the old methods until 3.0 (if ever), but while this is bit of nuisance, I think readability of sample code will improve. Too bad we didn't do this for 2.0 to eliminate the issue, but better late than never.

JsonLocation source ref should be marked as not serializable

(note: moved from https://jira.codehaus.org/browse/JACKSON-885)


JsonLocation is marked as serializable, and it is included as a member of JsonProcessingException, that is also serializable.

The problem is that JsonLocation has an Object attribute called _sourceRef, and this object is not always serializable.

This object can be a reference to a input stream and this input stream may not be serializable as it happen to me when trying to serialize a JsonProcessingException exception:

java.io.NotSerializableException: libcore.net.http.FixedLengthInputStream

I would advice to mark _sourceRef as volatile (not serializable). This will make it possible to serialize the exception without problems.

Map serialization, null values and @JsonValue

Jackson allows skip null values when serializing maps. This doesn't work, when map value is generated by the method annotated with @JsonValue. For example:

@JsonProperty
private Map<String, SomeClass> fields;

and:

class SomeClass {
@JsonValue
public String getValue() { ... }
}

result:

{"id1":"a","id2":null}

Updating existing entities

This request is to support updating of existing entities when inheritance is being used. It seems like everytime it just throws a UnsupportedException. We are using Jackson 1.9.11

Here is a test case:

import java.io.IOException;

import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.annotate.JsonSubTypes.Type;
import org.codehaus.jackson.annotate.JsonTypeInfo;
import org.codehaus.jackson.annotate.JsonTypeInfo.As;
import org.codehaus.jackson.annotate.JsonTypeInfo.Id;
import org.codehaus.jackson.annotate.JsonTypeName;
import org.codehaus.jackson.map.ObjectMapper;

public class TestUpdating {

    @JsonAutoDetect(getterVisibility=Visibility.NONE, setterVisibility=Visibility.NONE, isGetterVisibility=Visibility.NONE)
    @JsonTypeInfo(include=As.PROPERTY, use=Id.NAME, property="type")
    @JsonSubTypes(value={
            @Type(value=Child.class)})
     abstract static class Parent {
        @JsonProperty("x")
        int x;
        @JsonProperty("y")
        int y;

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

    }

    @JsonIgnoreProperties(ignoreUnknown=true)
    @JsonAutoDetect(getterVisibility=Visibility.NONE, setterVisibility=Visibility.NONE, isGetterVisibility=Visibility.NONE)
    @JsonTypeName("child")
     public static class Child extends Parent {
        @JsonProperty("w")
        int w;
        @JsonProperty("h")
        int h;

        public int getW() {
            return w;
        }

        public void setW(int w) {
            this.w = w;
        }

        public int getH() {
            return h;
        }

        public void setH(int h) {
            this.h = h;
        }

    }

    public static void main(String[] args) {
        Child c = new Child();
        c.setW(10);
        c.setH(11);
        ObjectMapper mapper = new ObjectMapper();
        try {
            mapper.readerForUpdating(c).readValue("{\"x\":3,\"y\":4}");
            System.out.println(c.getX());
            System.out.println(c.getY());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Add support for YAML comments as an option

Regrettably it looks like YAML does not support C or C++ comments but only scripting comments (hash sign until end of the line). While this should not cause problems with JSON per se, there are some cases where this is problematic: specifically, when YAML is viewed as a superset of JSON; in which case one has no common comments (granted, comments are not in standard JSON, so it is superset of standard JSON).

Anyway: ability to enable handling of "hash comments" would be useful and simple to implement; quite similar to how C++ comments are handled. As such, it would make sense to add in 2.2.

deserializing for type mismatch

I am getting a response like this from a pHp(cakePhp) server :
[
{
"id": "42389",
"start": "0000-00-00",
"end": "0000-00-00",
"event_id": null,
"trip_id": "5791",
"location_id": "231552",
"user_id": "105",
"users_attending": "0",
"user_local": "0",
"Trip": {
"name": "Asdas"
},
"Event": [],
"Location": {
"name": "South Melbourne"
}
},
{
"id": "42392",
"start": "0000-00-00",
"end": "0000-00-00",
"event_id": "1218",
"trip_id": "4772",
"location_id": "271505",
"user_id": "105",
"users_attending": "3",
"user_local": "50",
"Trip": {
"name": "trip by 1059200"
},
"Event": {
"title": "SampleEvent 454",
"id": "1218"
},
"Location": {
"name": "Houston"
}
},
.......
]

The thing is that the parser expects Event object but if its null then it is receiving empty array and throws com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of out of START_ARRAY token

On iOS restkit handles it automatically. but with Jackson I have to create Custom deserializer for Event Object which affects performance.

Is there any better way to do this.

I have put this on StackOverflow too (http://stackoverflow.com/questions/12684808/jackson-parser-ignore-deserializing-for-type-mismatch/) and (http://stackoverflow.com/questions/13175420/jackson-deserializing-with-custom-deserializer-causes-a-lot-of-gc-calls-and-take)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.