fasterxml / jackson-datatype-guava Goto Github PK
View Code? Open in Web Editor NEW(DEPRECATED) -- moved under `jackson-datatypes-collections`
Home Page: http://wiki.fasterxml.com/JacksonModuleGuava
(DEPRECATED) -- moved under `jackson-datatypes-collections`
Home Page: http://wiki.fasterxml.com/JacksonModuleGuava
In oss-parent since version 11 there is improvement which allows to use bundle packaging.
As per discussion on Jackson-dev list, serialization inclusion checks for various "optional" types should work such that 'absent' value is NOT considered null-equivalent (only actual Java null should qualify), but need to be considered "empty" (and "default" where applicable, usually absent would be included but it depends).
This means a change for Guava module to get it in line with JDK8 Optional, and other similar referential types.
Since this is backwards incompatible change, an additional configuration property should be added in GuavaModule
. Whether it should default to existing 2.5 behavior or not is open to discussion -- at this point I assume it should.
(moved from FasterXML/jackson-databind#517 reported by @chisui)
In 2.4.1.3 this works
new ObjectMapper().writeValueAsString(new Iterable<Integer>() {
@Override
public Iterator<Integer> iterator() {
return ImmutableList.of(1, 2, 3).iterator();
}
});
but this doesn't.
new ObjectMapper().writeValueAsString(Iterables.limit(Iterables.cycle(1,2,3), 3));
Can't work out quite why I'm getting this, but I am:
Exception in thread "main" java.lang.VerifyError: class com.fasterxml.jackson.datatype.guava.deser.HostAndPortDeserializer overrides final method deserialize.(Lcom/fasterxml/jackson/core/JsonParser;Lcom/fasterxml/jackson/databind/DeserializationContext;)Ljava/lang/Object;
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ project ---
[INFO] com.mycompany:project:jar:1.0-SNAPSHOT
[INFO] +- org.projectlombok:lombok:jar:1.14.8:compile
[INFO] +- io.dropwizard:dropwizard-core:jar:0.8.0-rc1:compile
[INFO] | +- io.dropwizard:dropwizard-util:jar:0.8.0-rc1:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.4.0:compile
[INFO] | | +- com.google.guava:guava:jar:18.0:compile
[INFO] | | +- com.google.code.findbugs:jsr305:jar:3.0.0:compile
[INFO] | | \- joda-time:joda-time:jar:2.5:compile
[INFO] | +- io.dropwizard:dropwizard-jackson:jar:0.8.0-rc1:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-core:jar:2.4.3:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-databind:jar:2.4.3:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk7:jar:2.4.3:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-guava:jar:2.4.3:compile
[INFO] | | +- com.fasterxml.jackson.module:jackson-module-afterburner:jar:2.4.3:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-joda:jar:2.4.3:compile
[INFO] | | +- org.slf4j:slf4j-api:jar:1.7.7:compile
[INFO] | | \- ch.qos.logback:logback-classic:jar:1.1.2:compile
[INFO] | +- io.dropwizard:dropwizard-validation:jar:0.8.0-rc1:compile
[INFO] | | +- org.hibernate:hibernate-validator:jar:5.1.3.Final:compile
[INFO] | | | +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO] | | | +- org.jboss.logging:jboss-logging:jar:3.1.3.GA:compile
[INFO] | | | \- com.fasterxml:classmate:jar:1.0.0:compile
[INFO] | | \- org.glassfish.web:javax.el:jar:2.2.6:compile
[INFO] | | \- javax.el:javax.el-api:jar:2.2.5:compile
[INFO] | +- io.dropwizard:dropwizard-configuration:jar:0.8.0-rc1:compile
[INFO] | | +- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:jar:2.4.3:compile
[INFO] | | \- org.apache.commons:commons-lang3:jar:3.3.2:compile
[INFO] | +- io.dropwizard:dropwizard-logging:jar:0.8.0-rc1:compile
[INFO] | | +- io.dropwizard.metrics:metrics-logback:jar:3.1.0:compile
[INFO] | | +- org.slf4j:jul-to-slf4j:jar:1.7.7:compile
[INFO] | | +- ch.qos.logback:logback-core:jar:1.1.2:compile
[INFO] | | +- org.slf4j:log4j-over-slf4j:jar:1.7.7:compile
[INFO] | | +- org.slf4j:jcl-over-slf4j:jar:1.7.7:compile
[INFO] | | \- org.eclipse.jetty:jetty-util:jar:9.2.4.v20141103:compile
[INFO] | +- io.dropwizard:dropwizard-metrics:jar:0.8.0-rc1:compile
[INFO] | +- io.dropwizard:dropwizard-jersey:jar:0.8.0-rc1:compile
[INFO] | | +- org.glassfish.jersey.core:jersey-server:jar:2.13:compile
[INFO] | | | +- org.glassfish.jersey.core:jersey-common:jar:2.13:compile
[INFO] | | | | +- org.glassfish.jersey.bundles.repackaged:jersey-guava:jar:2.13:compile
[INFO] | | | | \- org.glassfish.hk2:osgi-resource-locator:jar:1.0.1:compile
[INFO] | | | +- org.glassfish.jersey.core:jersey-client:jar:2.13:compile
[INFO] | | | +- javax.ws.rs:javax.ws.rs-api:jar:2.0.1:compile
[INFO] | | | +- javax.annotation:javax.annotation-api:jar:1.2:compile
[INFO] | | | +- org.glassfish.hk2:hk2-api:jar:2.3.0-b10:compile
[INFO] | | | | +- org.glassfish.hk2:hk2-utils:jar:2.3.0-b10:compile
[INFO] | | | | \- org.glassfish.hk2.external:aopalliance-repackaged:jar:2.3.0-b10:compile
[INFO] | | | +- org.glassfish.hk2.external:javax.inject:jar:2.3.0-b10:compile
[INFO] | | | \- org.glassfish.hk2:hk2-locator:jar:2.3.0-b10:compile
[INFO] | | | \- org.javassist:javassist:jar:3.18.1-GA:compile
[INFO] | | +- org.glassfish.jersey.ext:jersey-metainf-services:jar:2.13:compile
[INFO] | | +- io.dropwizard.metrics:metrics-jersey2:jar:3.1.0:compile
[INFO] | | +- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:2.4.3:compile
[INFO] | | | +- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:2.4.3:compile
[INFO] | | | \- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.4.3:compile
[INFO] | | +- org.glassfish.jersey.containers:jersey-container-servlet:jar:2.13:compile
[INFO] | | | \- org.glassfish.jersey.containers:jersey-container-servlet-core:jar:2.13:compile
[INFO] | | +- org.eclipse.jetty:jetty-server:jar:9.2.4.v20141103:compile
[INFO] | | | +- javax.servlet:javax.servlet-api:jar:3.1.0:compile
[INFO] | | | \- org.eclipse.jetty:jetty-io:jar:9.2.4.v20141103:compile
[INFO] | | +- org.eclipse.jetty:jetty-webapp:jar:9.2.4.v20141103:compile
[INFO] | | | \- org.eclipse.jetty:jetty-xml:jar:9.2.4.v20141103:compile
[INFO] | | \- org.eclipse.jetty:jetty-continuation:jar:9.2.4.v20141103:compile
[INFO] | +- io.dropwizard:dropwizard-servlets:jar:0.8.0-rc1:compile
[INFO] | | \- io.dropwizard.metrics:metrics-annotation:jar:3.1.0:compile
[INFO] | +- io.dropwizard:dropwizard-jetty:jar:0.8.0-rc1:compile
[INFO] | | +- io.dropwizard.metrics:metrics-jetty9:jar:3.1.0:compile
[INFO] | | +- org.eclipse.jetty:jetty-servlet:jar:9.2.4.v20141103:compile
[INFO] | | | \- org.eclipse.jetty:jetty-security:jar:9.2.4.v20141103:compile
[INFO] | | +- org.eclipse.jetty:jetty-servlets:jar:9.2.4.v20141103:compile
[INFO] | | \- org.eclipse.jetty:jetty-http:jar:9.2.4.v20141103:compile
[INFO] | +- io.dropwizard:dropwizard-lifecycle:jar:0.8.0-rc1:compile
[INFO] | +- io.dropwizard.metrics:metrics-core:jar:3.1.0:compile
[INFO] ------------------------------------------------------------------------```
Is there a way to configure ObjectMapper to pick up the GuavaModule without having the explicit call? I'm using Jackson in conjunction with CXF (REST) and does not have a handle to the ObjectMapper instance.
Basic example of Optional serialization:
public static class MyData { public final Optional myOptional; @JsonCreator public MyData(@JsonProperty("myOptional") final Optional optional) { this.myOptional = optional; } }
final ObjectMapper objectMapper = new ObjectMapper(); // ENABLE TYPING objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); objectMapper.registerModule(new GuavaModule()); final Optional optional = Optional.fromNullable(""); final MyData myData = new MyData(optional ); // SERIALIZATION objectMapper.writeValueAsString(myData );
Exception:
com.fasterxml.jackson.databind.JsonMappingException: Type id handling not implemented for type com.google.common.base.Present (through reference chain: com.neotys.MyData["myOptional"]) ... at com.fasterxml.jackson.datatype.guava.ser.GuavaOptionalBeanPropertyWriter.serializeAsField(GuavaOptionalBeanPropertyWriter.java:23) ...
Hi there. I'm running into some issues with distributing the source for the latest version of jackson-datatype-guava, in particular the contributor agreement under the DEV directory. It also seems to be at odds with the Apache 2.0 license that the module is currently distributed under.
Is it OK to strip this PDF from the source?
Regards,
Tim.
Consider the example:
public class Test {
public static void main(String[] args) throws JsonProcessingException {
System.out.println(new ObjectMapper()
.registerModule(new GuavaModule())
.writeValueAsString(new Parent()));
}
}
class Child {
@JsonProperty
private String text = "hello, world!";
}
class Parent {
@JsonProperty
@JsonUnwrapped
private Child child = new Child();
}
Produces: {"text":"hello, world!"}
Whereas the following example:
public class Test {
public static void main(String[] args) throws JsonProcessingException {
System.out.println(new ObjectMapper()
.registerModule(new GuavaModule())
.writeValueAsString(new Parent()));
}
}
class Child {
@JsonProperty
private String text = "hello, world!";
}
class Parent {
@JsonProperty
@JsonUnwrapped
private Optional<Child> child = Optional.of(new Child());
}
(note, that the child
field is now Optional)
Produces: {"child":{"text":"hello, world!"}}
Such a behaviour looks a bit odd and counterintuitive. In my opinion, the output should be the same as in the first case.
Should be able to have
enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
class Foo {
public Multimap<String,String> bar;
}
with JSON
{
bar: "qux"
}
However, this throws exception:
JsonMappingException: Expecting START_ARRAY, found VALUE_STRING
Please note that this works:
class Foo {
List<String> bar;
}
with JSON:
{
bar: "qux"
}
when enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
Hi,
Not sure if this has been reported before. 'null' insideList<Optional>
failed to deserialize to Optional.absent()
. This problem exists in the latest 2.3.1 code.
As a side node,List<List<String>>
works, so I assume it's not about generics or String not being able to deserialize null. It also works when Optional
is inside the object with List<JacksonObject>
.
Below test case failed due to inconsistency of List<Optional>
deserialization.
@Test
public void testOptionalCollection() throws Exception {
ObjectMapper mapper = new ObjectMapper().registerModule(new GuavaModule());
TypeReference<List<Optional<String>>> typeReference =
new TypeReference<List<Optional<String>>>() {};
List<Optional<String>> list = new ArrayList<>();
list.add(Optional.of("2014-1-22"));
list.add(Optional.<String>absent());
list.add(Optional.of("2014-1-23"));
String str = mapper.writeValueAsString(list);
assertEquals("[\"2014-1-22\",null,\"2014-1-23\"]", str);
List<Optional<String>> serializedList = mapper.readValue(str, typeReference);
assertEquals(list, serializedList);
}
This following test case works.
@Test
public void testObjectWithOptionalCollection() throws Exception {
ObjectMapper mapper = new ObjectMapper().registerModule(new GuavaModule());
List<OptionalInJackson> listOptional = new ArrayList<>();
OptionalInJackson optionalJackson = new OptionalInJackson();
optionalJackson.setStr(Optional.of("THE WORST"));
listOptional.add(optionalJackson);
OptionalInJackson empty = new OptionalInJackson();
empty.setStr(Optional.<String>absent());
listOptional.add(empty);
String str = mapper.writeValueAsString(listOptional);
assertEquals("[{\"str\":\"THE WORST\"},{\"str\":null}]", str);
List<OptionalInJackson> fine = mapper.readValue(str, new TypeReference<List<OptionalInJackson>>() {});
assertEquals(listOptional, fine);
}
static class OptionalInJackson {
@JsonProperty("str")
private Optional<String> str;
OptionalInJackson(){
str = Optional.absent();
}
public void setStr(Optional<String> opt) {
str = opt;
}
public Optional<String> getStr() {
return str;
}
@Override
public boolean equals(Object other) {
if (other == null) return false;
return StringUtils.equals(toString(), other.toString());
}
@Override
public String toString() {
return str.toString();
}
}
In com.fasterxml.jackson.datatype.guava.deser.GuavaOptionalDeserializer#deserialize(JsonParser, DeserializationContext)
, there is a possible bug of calling Optional.of(null)
when the given value is the String "null"
and the expected type is Optional<Integer>
(tested also on Optional<Float>
).
Calling Optional.of(null)
triggers a NullPointerException.
In my opinion, the expected behavior in that case is returning Optional.absent()
by calling Optional.fromNullable(refd)
.
Here is the relevant code:
@Override
public Optional<?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
Object refd;
if (_valueTypeDeserializer == null) {
refd = _valueDeserializer.deserialize(jp, ctxt); // This returns null when the given value is the String "null"
} else {
refd = _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
}
return Optional.of(refd); // and then this throws NullPointerException
}
Does it support guava v14.0.1?
The Import-Package
OSGi directive in the Manifest.MF
is generated using the (reasonable) "this version to next major version" algorithm. Unfortunately, Guava releases are all major version releases (15,16,17).
Import-Package: com.google.common.collect;version="[15.0,16)",com.google
.common.base;version="[15.0,16)",com.google.common.cache;version="[15.0
,16)",com.google.common.hash;version="[15.0,16)",com.google.common.net;
version="[15.0,16)"
The (current) latest release is 18.0.0 (bundle version). Given Guava's commitment to backward compatibility (esp. in their collections), it would be more reasonable to not version restrict the package imports for Guava. Or at least the open-ended, just "15.0.0"
.
Currently, multisets' serialization size is proportional to Multiset.size() as opposed to Multiset.entrySet().size().
For example, if I have do Multiset.setCount("my_key", 1000), "my_key" is repeated 1000 times in the output. It would be much more appropriate if it behaved liked Map<String, Integer>.
As you can see in the following gist if scala module is defined after guava module then there is an error deserializing a pojo with a multi-map property.
Not sure if the bug is in the scala module or guava module so I'm opening the same ticket on both and I'd appreciate you figuring out who is at fault here.
https://gist.github.com/ittaiz/6174553
issue on scala-module: FasterXML/jackson-module-scala#95
(moved from FasterXML/jackson-databind#665 by @prb)
This issue is an old one apparently:
https://jira.codehaus.org/browse/JACKSON-876
Here's a minimal reproduction:
Iterables.transform(ImmutableList.of("mr", "bo", "jangles"),
new Function<String, String>() {
@Override
public String apply(@Nullable String input) {
return new StringBuffer(input).reverse().toString();
}
})
Guava's HostAndPort class doesn't work out-of-the-box with Jackson because it's factory method is named fromString
rather than the standard valueOf
.
There was a Guava issue 1083 filed a while ago but it's doubtful they will fix it. I also filed FasterXML/jackson-databind#208 to support fromString
directly in Jackson, but it might be worth fixing here first depending on if/when that makes it into Jackson.
There are a few TODOs in the source code of GuavaDeserializers
. For example:
The ImmutableSetMultimap
one matters to me because the default deserializer does not have the same semantics for traversal order of entries. The order of the entries in the source is important, but it is lost in deserialization when it is put into a HashMultimap
.
I imagine it could be a one line fix, by defaulting to LinkedHashMultimap
instead. But I bet that's not what the person who wrote that TODO had in mind.
In general, for TODOs like this one, do you want pull requests?
Deserializing an array with a null element will result in the ImmutableList throwing a nullpointer.
Is there a setting to ignore nulls, is this the expected behaviour or can the library be updated to ignore nulls based on a setting ?
Or should ignoring the nulls be default behaviour ?
Are there any alternatives, I don't see any utility in the current module?
See #80.
The version constraint in the OSGi metadata is very strict, so it demands a very particular version of Guava.
(related to https://github.com/FasterXML/jackson-datatype-jdk8/issues/14)
Looks like handling of polymorphic value types does not work properly with 2.6[.1].
Any chance to add support for TransformingRandomAccessList?
What can be done to support Table deserialization?
I only see a "TODO".
Just upgraded my project dependencies to 2.6.2 (from 2.5.1), starting seeing an exception on serialization complaining about com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter not being found. Looks like the guava module jar does not have an import directive for that package. Ideally, it shouldn't have to since you guys aren't using that class directly. However, in order for it to all work, the package you're importing from needs to have "uses" directives attached to their Export-Package entries which specify their transitive package dependencies.
I've just updated from 2.4.0 to 2.6.0 and now I'm getting this error when serializing Guava types:
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.type.TypeFactory.constructParametrizedType(Ljava/lang/Class;Ljava/lang/Class;[Lcom/fasterxml/jackson/databind/JavaType;)Lcom/fasterxml/jackson/databind/JavaType;
at com.fasterxml.jackson.datatype.guava.GuavaTypeModifier.modifyType(GuavaTypeModifier.java:106)
at com.fasterxml.jackson.databind.type.TypeFactory._constructType(TypeFactory.java:414)
at com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeFactory.java:358)
at com.fasterxml.jackson.databind.cfg.MapperConfig.constructType(MapperConfig.java:268)
at com.fasterxml.jackson.databind.cfg.MapperConfig.introspectClassAnnotations(MapperConfig.java:298)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.removeIgnorableTypes(BeanSerializerFactory.java:651)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanProperties(BeanSerializerFactory.java:522)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanSerializer(BeanSerializerFactory.java:344)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanSerializer(BeanSerializerFactory.java:263)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:222)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:152)
at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1108)
at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1068)
at com.fasterxml.jackson.databind.SerializerProvider.findPrimaryPropertySerializer(SerializerProvider.java:585)
at com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap.findAndAddPrimarySerializer(PropertySerializerMap.java:69)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._findAndAddDynamic(BeanPropertyWriter.java:668)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:483)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21)
at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:505)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:128)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1902)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:167)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:291)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:146)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration$MetricsFilter.doFilterInternal(MetricFilterAutoConfiguration.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Any idea on what can cause this?
I've tried to use guava module and looks pretty useful to me. But there is small glitch which spoiled the pleasure then no type information supplied - got null pointer exception with no explanation
com.fasterxml.jackson.datatype.guava.deser.MultimapDeserializer, Line 98
Did you mean this :
if (elementTypeDeserializer != null)
{
builder.put(key, elementDeserializer.deserializeWithType(jp, ctxt, elementTypeDeserializer));
}
Instead iof this :
if (elementDeserializer != null)
โฆ.
Im using 2.0.2 version. Sorry if it was already fixed
This is kind of a strange issue, which I can't really describe well except by the unit test below. When a Guava Optional wraps a generic type (eg. a Collection
), the generic type information seems to be lost somewhere along the way, and the visitor does not actually visit the properties of the generic type.
In the following code, the test fails using 2.6.0-rc3
and higher (2.6.2
included), but succeeds with 2.6.0-rc2
. The expected output is [values.data, values, values.data.value]
, but the actual output is [values.data, values]
.
While debugging, I found out that in the method GuavaOptionalSerializer#acceptJsonFormatVisitor
the generic type information of Collection
is lost, and it thinks the type is Object
, not ValueHolder
, but the code was a bit too complex for me to figure out why or how. It seems to me the issue might have been in changeset eb6b98a but I'm not sure.
By the way, this works fine with Jdk8Module
and java.util.Optional
.
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsonFormatVisitors.*;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.google.common.base.Optional;
import org.junit.Assert;
import org.junit.Test;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class OptionalGenericTest {
@Test
public void testGeneric() throws Exception {
VisitorWrapper wrapper = new VisitorWrapper(null, "", new HashSet<>());
new ObjectMapper()
.registerModule(new GuavaModule())
.acceptJsonFormatVisitor(TopLevel.class, wrapper);
Set<String> properties = wrapper.getTraversedProperties();
System.out.println(properties);
Assert.assertTrue(properties.contains("values.data.value"));
}
public class TopLevel {
@JsonProperty("values")
public Optional<CollectionHolder<ValueHolder>> values;
}
public class ValueHolder {
@JsonProperty("value")
public String value;
}
public class CollectionHolder<T> {
@JsonProperty("data")
public Collection<T> data;
}
public static class VisitorWrapper implements JsonFormatVisitorWrapper {
private SerializerProvider serializerProvider;
private final String baseName;
private final Set<String> traversedProperties;
public VisitorWrapper(SerializerProvider serializerProvider, String baseName, Set<String> traversedProperties) {
this.serializerProvider = serializerProvider;
this.baseName = baseName;
this.traversedProperties = traversedProperties;
}
private VisitorWrapper createSubtraverser(String baseName) {
return new VisitorWrapper(getProvider(), baseName, traversedProperties);
}
public Set<String> getTraversedProperties() {
return traversedProperties;
}
@Override
public JsonObjectFormatVisitor expectObjectFormat(JavaType type) throws JsonMappingException {
return new JsonObjectFormatVisitor.Base(serializerProvider) {
@Override
public void property(BeanProperty prop) throws JsonMappingException {
anyProperty(prop);
}
@Override
public void optionalProperty(BeanProperty prop) throws JsonMappingException {
anyProperty(prop);
}
private void anyProperty(BeanProperty prop) throws JsonMappingException {
final String propertyName = prop.getFullName().toString();
traversedProperties.add(baseName + propertyName);
serializerProvider.findValueSerializer(prop.getType(), prop)
.acceptJsonFormatVisitor(createSubtraverser(baseName + propertyName + "."), prop.getType());
}
};
}
@Override
public JsonArrayFormatVisitor expectArrayFormat(JavaType type) throws JsonMappingException {
serializerProvider.findValueSerializer(type.getContentType())
.acceptJsonFormatVisitor(createSubtraverser(baseName), type.getContentType());
return new JsonArrayFormatVisitor.Base(serializerProvider);
}
@Override
public JsonStringFormatVisitor expectStringFormat(JavaType type) throws JsonMappingException {
return new JsonStringFormatVisitor.Base();
}
@Override
public JsonNumberFormatVisitor expectNumberFormat(JavaType type) throws JsonMappingException {
return new JsonNumberFormatVisitor.Base();
}
@Override
public JsonIntegerFormatVisitor expectIntegerFormat(JavaType type) throws JsonMappingException {
return new JsonIntegerFormatVisitor.Base();
}
@Override
public JsonBooleanFormatVisitor expectBooleanFormat(JavaType type) throws JsonMappingException {
return new JsonBooleanFormatVisitor.Base();
}
@Override
public JsonNullFormatVisitor expectNullFormat(JavaType type) throws JsonMappingException {
return new JsonNullFormatVisitor.Base();
}
@Override
public JsonAnyFormatVisitor expectAnyFormat(JavaType type) throws JsonMappingException {
return new JsonAnyFormatVisitor.Base();
}
@Override
public JsonMapFormatVisitor expectMapFormat(JavaType type) throws JsonMappingException {
return new JsonMapFormatVisitor.Base(serializerProvider);
}
@Override
public SerializerProvider getProvider() {
return serializerProvider;
}
@Override
public void setProvider(SerializerProvider provider) {
this.serializerProvider = provider;
}
}
}
The Guava Table<R, C, V>
data structure is a convenience wrapper around a Map<R, Map<C, V>>
. This form can be easily serialized and deserialized. Here's the basic code I'm using for that:
public static class TableSerializer extends JsonSerializer<Table<?, ?, ?>> {
@Override
public void serialize(final Table<?, ?, ?> value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeObject(value.rowMap());
}
@Override
public Class<Table<?, ?, ?>> handledType() {
return (Class)Table.class;
}
} // end class TableSerializer
public static class TableDeserializer extends JsonDeserializer<Table<?, ?, ?>> {
@Override
public Table<?, ?, ?> deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException {
final ImmutableTable.Builder<Object, Object, Object> tableBuilder = ImmutableTable.builder();
final Map<Object, Map<Object, Object>> rowMap = jp.readValueAs(Map.class);
for (final Map.Entry<Object, Map<Object, Object>> rowEntry : rowMap.entrySet()) {
final Object rowKey = rowEntry.getKey();
for (final Map.Entry<Object, Object> cellEntry : rowEntry.getValue().entrySet()) {
final Object colKey = cellEntry.getKey();
final Object val = cellEntry.getValue();
tableBuilder.put(rowKey, colKey, val);
}
}
return tableBuilder.build();
}
} // end class TableDeserializer
I have not tested if this correctly supports contextual keys or type (de)serialization. I looked at MultimapSerializer
and MultimapDeserializer
, and they are much more complicated even though a Multimap<K, V>
is just a convenience wrapper around Map<K, Collection<V>>
, so maybe this is too simplistic?
Notably, this implementation always deserializes to an ImmutableTable
. Heuristics could be used to determine what Table
implementation to reconstruct, e.g., if every row, column value is non-null, could create ArrayTable
. HashBasedTable
would be a good mutable default.
I'm just going to put the following image first as it's a bit difficult to explain otherwise.
I'm using dropwizard 0.7.0 which is using Jackson 2.3.1 and Guava 16.0.1.
As you can see on the code, if I serialize and deserialize from/to multimap; everything seems to be fine. multimap json is in order and deserialized in the same order.
But when I enter my own JSON, which is pretty similar, it's completely reversed as it can be seen on multimap2.
And this breaks all my tests after I changed a few class fields from Map to Multimap. (I know there is no real order in maps but it still breaks my tests :))
Current latest Guava is at version 17.0, this module works with Guava 15.0.
Wiil there be a problem if I override the dependency to guava 17?
Hello,
I am having trouble serializing FluentIterable
classes. I am using Jackson 2.3.2 and Guava 15.0. This seems a lot like the issue reported here:
http://jackson-users.ning.com/forum/topics/serializing-guava-fluentiterable
And fixed here:
And also possibly related to this issue in code:
https://jira.codehaus.org/browse/JACKSON-698
I'm wondering if it is a regression of some type.
My code looks like this:
Iterable<NewObj> newObjects = FluentIterable.from(myObjects)
.filter(new Predicate<MyObj>() {
@Override
public boolean apply(MyObj obj) {
// logic here
}
})
.transform(new Function<MyObj, NewObj>() {
public NewObj apply(MyObj myObj) {
return new NewObj(myObj);
}
});
Results in JSON like this:
{
"newObjects" : {
"empty" : false
}
}
Any help would be appreciated.
Similiar to #43, we may want to support deserialization of CacheBuilderSpec
as well
The code below will give the following json object:
{"someMap" : { }}
and I would expect
{ }
This happens also when I confiugre the mapper to:
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
@JsonInclude(JsonInclude.Include.NON_EMPTY)
class MainClass {
@JsonProperty
Multimap<String, String> someMap = ArrayListMultimap.create();
}
com.fasterxml.jackson.datatype.guava.deser.MultimapDeserializer
seems to always expect an array and doesn't even check for DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY
at any point.
(In my case, I'm trying to convert a Java bean containing both primitive values and a list of strings into a Multimap. Since http://jira.codehaus.org/browse/JACKSON-592 is not resolved, I don't think there is a simple workaround for the problem of getting Expecting START_ARRAY, found VALUE_NUMBER_INT
IllegalArgumentException, either.)
The GuavaMapDeserializer#deserialize() method does not correctly deserialize empty ImmutableMap object instances when they are nested as bean properties and have a "@Class" identifier as the first key/value pair in the enclosing curly braces. Note that "empty" implies that there are no additional key/value pairs after the class identifier in question, which results in parsing error.
More specifically, the parsing issue stems from the check on line 120 where, JsonToken.END_OBJECT is NOT considered as a legitimate first token, and a run-time exception is raised. Note that the regular MapDeserializer class DOES permit the END_OBJECT token as a legitimate first token.
Hi,
I am trying to serialize RangeSet using jackson 2.8 libraries. I am getting the following exception:
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.time.LocalDateTime and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.akash.test.Range.RangeInterval["rangeSet"]->com.google.common.collect.TreeRangeSet$AsRanges[0])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:284)
at com.fasterxml.jackson.databind.SerializerProvider.mappingException(SerializerProvider.java:1110)
at com.fasterxml.jackson.databind.SerializerProvider.reportMappingProblem(SerializerProvider.java:1135)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:69)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:32)
at com.fasterxml.jackson.datatype.guava.ser.RangeSerializer._writeContents(RangeSerializer.java:133)
at com.fasterxml.jackson.datatype.guava.ser.RangeSerializer.serialize(RangeSerializer.java:90)
at com.fasterxml.jackson.datatype.guava.ser.RangeSerializer.serialize(RangeSerializer.java:20)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContentsUsing(CollectionSerializer.java:176)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:120)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:112)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:689)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3697)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3073)
at com.akash.test.Range.RangeInterval.main(RangeInterval.java:38)
As per my understanding, it is trying to access the first element (i.e. TreeRangeSet$AsRanges[0]) of the set using index which I guess is not a valid option in the set.
It works great with jackson 2.6 libraries. Can anyone help me out?
Hello!
I want to deserialize an object like this, without explicitly inform lowerBoundType and upperBoundType:
{
foo: 'bar',
fooz: {
lowerEndpoint: 1,
upperEndpoint: 5
}
}
How can I configure the deserializer to aways set lowerBoundType and upperBoundType as 'CLOSED'?
Serializing a Multimap<K, ?> fails if K is any non-String type, even if intuitively it should work (e.g. K is a string-like type such as Enum, or K has an @JsonValue
annotation).
I couldn't figure out how this is supposed to work, so I have included failing test cases for both the 1.9 branch and 2.x branch and hope that someone else who knows more about how Jackson's typing works can help out.
As per name, this is one type DropWizard has custom deserializer for, seems useful.
#67 fixes deserialization of ImmutableSetMultimap but serialization still does not work. I tried serializing an ImmutableSetMultimap and got:
"theMap":
{
"empty": false
}
I am expecting the output to contain the map values.
public void testSerNonNull() throws Exception {
OptionalData data = new OptionalData();
data.myString = Optional.absent();
String value = mapperWithModule().setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(data);
assertEquals("{}", value);
}
I file this because I have the same issue (FasterXML/jackson-module-scala#32) in the Jackson Scala Module, and I want to make the argument to @cowtowncoder that we need support for this in JsonSerializer
. I could probably make it work in the Scala module by writing a custom BeanPropertyWriter
that does the right thing, but I think it'd be better to have a common solution for both projects.
It looks like some code could be borrowed from BeanSerializerBase.createContextual(), but the comments there seem to imply that such code would be better located in SerializerProvider.
Between 2.2.3 and 2.3.2 the technique of deserializing an optional polymorphic type using @JsonTypeInfo
and @JsonSubTypes
no longer seems to work. Without the Guava Optional<T>
everything works fine.
Self-contained example demonstrating the problem can be found here: https://gist.github.com/bbeck/934d787cc36c61c3e8a0
multimap with null values triggers null pointer exception at line 296
NOTE: moved from [https://jira.codehaus.org/browse/JACKSON-786]
Jackson returns {"empty":false} when serializing Guava TreeMultimaps. I attached a detailed test case.
Trying to upgrade to 2.7.0 jackson-datatype-guava, I'm getting exceptions "Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonInclude$Value". It looks like the import statement for that package is missing
Currently, I'm using a hacked up version of 2.6.2 using bnd to rewrite the manifest because that one was also missing entries.
(see FasterXML/jackson-databind#811 for background)
With 2.6 it is possible to cleanly support exclusion of null
s and "absent" Optional
s, without excluding empty List
s and such. But it needs bit of support from Guava module itself, to recognize Optional
as a reference type.
com.google.common.net.InternetDomainName
InternetDomainName#from(String domain) <-> InternetDomainName#toString()
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.